<template>
  <div ref="refComponent" class="t-import-export">
    <!--
      v-bind="{ ...attrs, ...mappingProps }"
      @click="onClickHandler"
    -->
    <ButtonDropdown
      v-show="mappingProps.visible"
      :label="
        (importConfig ? i18nTranslate(Terms.title.import.ReferenceExpr, '导入') : '') +
        (exportConfig ? i18nTranslate(Terms.title.export.ReferenceExpr, '导出') : '') +
        (!importConfig && !exportConfig ? i18nTranslate(Terms.title.notConfigured.ReferenceExpr, '导入导出尚未配置') : '')
      "
      icon="fas dx-icon icon-fasexportandimport"
      class="t-import-export-button-dropdown-father-prefix icon-shrink"
      :tabIndex="mappingProps.tabIndex"
    >
      <List class="t-import-export-list">
        <Item v-if="mappingProps.importConfig" class="item-wrap">
          <ItemSection @click="handleImport('click')" @keyup.enter="handleImport('enter')" @keyup.space="handleImport('space')" class="item-section" :tabIndex="mappingProps.tabIndex">
            <ItemLabel>
              <!-- dx-icon fas fasfont icon-fasimport dx-list-item-icon -->
              <Icon
                name="fas dx-icon icon-fasimport"
                class="t-import-export-button-dropdown-prefix icon-shrink"
              ></Icon>
              <span
                class="t-import-export-button-dropdown-prefix dropdown-button-text"
              >
                {{ ' ' + (mappingProps.importBtnName === '导入' ? i18nTranslate(Terms.title.import.ReferenceExpr, '导入') : mappingProps.importBtnName) }}
              </span>
            </ItemLabel>
          </ItemSection>
        </Item>
        <Item v-if="mappingProps.exportConfig" class="item-wrap">
          <ItemSection @click="handleExport2" @keyup.enter="handleExport2" @keyup.space="handleExport2" class="item-section" :tabIndex="mappingProps.tabIndex">
            <ItemLabel>
              <Icon
                name="fas dx-icon icon-fasexport"
                class="t-import-export-button-dropdown-prefix icon-shrink"
              ></Icon>
              <span
                class="t-import-export-button-dropdown-prefix dropdown-button-text"
              >
                {{ ' ' + (mappingProps.exportBtnName === '导出' ? i18nTranslate(Terms.title.export.ReferenceExpr, '导出') : mappingProps.exportBtnName) }}
              </span>
            </ItemLabel>
          </ItemSection>
        </Item>
        <Item v-if="mappingProps.importConfig" class="item-wrap">
          <ItemSection @click="dowmloadTemplate" @keyup.enter="dowmloadTemplate" @keyup.space="dowmloadTemplate" class="item-section" :tabIndex="mappingProps.tabIndex">
            <ItemLabel>
              <svg
                class="svg-icon"
                data-name=""
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 32 32"
              >
                <path
                  d="M20,9.91a1,1,0,0,0-1-1H7a1,1,0,0,0,0,2H19A1,1,0,0,0,20,9.91Zm-5,4.45H7a1,1,0,0,0,0,2h8a1,1,0,0,0,0-2Zm0,5.45H7a1,1,0,0,0,0,2h8a1,1,0,1,0,0-2Zm14.5.2H21.13l3.15-3.15a1,1,0,1,0-1.42-1.42L17.32,21l5.59,5.59a1,1,0,0,0,.71.3,1,1,0,0,0,.7-1.71L21.17,22H29.5a1,1,0,0,0,0-2ZM16.42,29H4.57A1.07,1.07,0,0,1,3.5,27.93V4.07A1.07,1.07,0,0,1,4.57,3H21.42A1.07,1.07,0,0,1,22.5,4.07v6.48a1,1,0,0,0,2,0V4.07A3.08,3.08,0,0,0,21.42,1H4.57A3.07,3.07,0,0,0,1.5,4.07V27.93A3.07,3.07,0,0,0,4.57,31H16.42a1,1,0,0,0,0-2Z"
                />
              </svg>
              <span
                class="t-import-export-button-dropdown-prefix dropdown-button-text"
              >
                {{ ' ' + i18nTranslate(Terms.title.ImportantTemplate.ReferenceExpr, '导入模板') }}</span
              >
            </ItemLabel>
          </ItemSection>
        </Item>
        <Item v-if="mappingProps.importConfig || mappingProps.exportConfig" class="item-wrap">
          <ItemSection @click="handleMissionList" @keyup.enter="handleMissionList" @keyup.space="handleMissionList" class="item-section"  :tabIndex="mappingProps.tabIndex">
            <ItemLabel>
              <Icon
                name="fas dx-icon icon-t-unordered-list"
                class="icon-shrink"
              ></Icon>
              <span
                class="t-import-export-button-dropdown-prefix dropdown-button-text"
              >
                {{ ' ' + i18nTranslate(Terms.title.taskList.ReferenceExpr, '任务列表') }}</span
              >
            </ItemLabel>
          </ItemSection>
        </Item>
        <Item v-if="!mappingProps.importConfig && !mappingProps.exportConfig" class="item-wrap">
          <ItemSection class="item-section">
            <ItemLabel>
              <span
                class="t-import-export-button-dropdown-prefix dropdown-button-text"
              >
                {{ i18nTranslate(Terms.title.nodata.ReferenceExpr, '没有要现实的数据') }}</span
              >
            </ItemLabel>
          </ItemSection>
        </Item>
      </List>
    </ButtonDropdown>

    <!-- 运行时 才有用到 -- 可加入判定 -> !inDesign , 没必要, 本身是隐藏的 -->
    <input
      v-if="uplaodFile"
      ref="upload"
      class="input-upload"
      type="file"
      accept="application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      @change="getFile($event)"
      tabindex="-1"
    />

    <t-dialog
      ref="dialogMissionList"
      v-model:show="dialog"
      class="t-import-export-dialog dialog-mission-list"
    >
      <t-card style="width: 1300px; max-width: 1300px" class="dialog-wrap">
        <t-card-section class="row items-center q-pb-none dialog-title">
          <div class="">{{ i18nTranslate(Terms.title.taskList.ReferenceExpr, '任务列表') }}</div>
          <t-space />
          <!--
            <t-button icon="close" flat round dense v-close-popup />
            不使用 v-close-popup 的形式关闭弹窗, 运行时不支持, 改为 click 形式
          -->
          <!-- <t-button icon="close" flat round dense @click="dialog = false" /> -->
          <t-button icon="close" class="tr-button-icon-text font-size-standard" :tabIndex="mappingProps.tabIndex" @click="dialog = false" />
        </t-card-section>

        <t-card-section
          class="row items-center q-pb-none card-section-content padding-top-0"
          :style="{ 'min-height2': '693px', 'padding-top': '2px' }"
        >
          <!-- 上方 padding-top 多了2px, 是为了凑齐 40px 的间距 （任务列表 和 导入任务tab 间)  -->
          <!-- 使用二次封装的 -->
          <!-- 不用 change 而用 click，避免初始化的时候重复调用接口
            @change=" e => handleChangeTab(e)" -->
          <t-tabs
            :ref="el => handleListenTabs(el)"
            class="standard-tabs"
            align="left"
            @click="e => handleClickTab(e)"
            :staticItems="tabList"
            :swipeable="false"
            :tabIndex="mappingProps.tabIndex"
          >
            <!-- modify -->
            <t-tab-panel :name="0">
              <div class="func-line">
                <p class="tips">{{ tipsWord }}</p>
                <div class="button-group">
                  <t-button
                    :disabled="!(rowsIm && rowsIm.length && rowsIm.length > 0)"
                    icon="fas dx-icon icon-t-delete-outlined"
                    :label="i18nTranslate(Terms.title.clearnImportTask.ReferenceExpr, '清空导入任务')"
                    class="tr-button-default"
                    align="left"
                    @click="clearnImportList"
                    :tabIndex="mappingProps.tabIndex"
                  ></t-button>
                  <!-- <Icon
                    name="refresh"
                    class="custom-icon-refresh"
                    color="primary"
                    alt="刷新"
                    @click="getTaskList('Refresh')"
                    @keyup.enter="getTaskList('Refresh')"
                    @keyup.space="getTaskList('Refresh')"
                    :tabIndex="mappingProps.tabIndex"
                  /> -->
                  <t-button
                    icon="refresh"
                    label=""
                    class="tr-button-icon-text custom-icon-refresh"
                    @click="getTaskList('Refresh')"
                    :tabIndex="mappingProps.tabIndex"
                  />
                </div>
              </div>
              <template v-if="rowsIm && rowsIm.length && rowsIm.length > 0">
                <template
                  v-if="false"
                  alt="注释: flagcomment 导入任务 列表"
                ></template>
                  <!--
                    pagination 里面有了 rowsNumber 参数，便不会触发 @update:pagination, 而是触发 @request
                    :pagination="pagination"
                  @update:pagination="updatePagination" -->
                <Table
                  :rows="rowsIm"
                  :columns="columnsIm"
                  row-key="ID"
                  flat
                  class="my-sticky-column-table"
                  v-model:pagination="pagination"
                  @request="onRequest"
                  :rows-per-page-options="rowsPerPageOptions"
                  :tabIndex="mappingProps.tabIndex"
                >
                  <!-- mappingProps.paginationLabel || getPaginationLabel -->
                  <template v-slot:body-cell-State="props">
                    <t-td :props="props">
                      <div @click="handleClickState(props)">
                        <SpinnerIos
                          v-show="props.row.State === 0"
                          title="加载中"
                          color="orange"
                          size="18px"
                          :tabIndex="-1"
                        />
                        <Icon
                          v-show="props.row.State === 1"
                          title="成功"
                          color="green"
                          name="done"
                          name2="check_circle_outline"
                          size="18px"
                          :tabIndex="-1"
                        />
                        <Icon
                          v-show="props.row.State === 2"
                          title="部分成功"
                          color="orange"
                          name="info"
                          size="18px"
                          :tabIndex="-1"
                        />
                        <Icon
                          v-show="props.row.State === 3"
                          :title="i18nTranslate(Terms.title.failTips.ReferenceExpr, '失败')"
                          color="red"
                          name="close"
                          name2="close_circle_outline"
                          size="18px"
                          :tabIndex="-1"
                        />
                      </div>
                    </t-td>
                  </template>
                  <template v-slot:body-cell-Operation="props">
                    <t-td :props="props">
                      <div class="operation-line">
                        <t-button
                          v-if="
                            (props.row.State == 2 || props.row.State == 3) &&
                            (importConfigComputed?.hasOwnProperty(
                              'IsEnableUniqueCol',
                            )
                              ? importConfigComputed.IsEnableUniqueCol
                              : true)
                          "
                          class="button-span primary-color pointer font-size-standard tr-button-text"
                          @click="tautology($event)"
                          :tabIndex="mappingProps.tabIndex"
                        >
                          {{ i18nTranslate(Terms.title.retry.ReferenceExpr, '重试') }}
                          <input
                            v-if="uploadFile2"
                            class="input-upload"
                            type="file"
                            accept=".csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                            @change="getFile($event, 'again', props.row)"
                            :tabIndex="-1"
                          />
                        </t-button>
                        <template
                          v-if="false"
                          alt="注释: flagcomment 导入文件下载 - 仅限 2-部分失败 和 3-失败 的展示下载，1-成功 的不展示"
                        ></template>
                        <t-button
                          v-if="props.row.State == 2 || props.row.State == 3"
                          class="button-span primary-color pointer font-size-standard tr-button-text"
                          @click="downloadExcel(props.row, 'download')"
                          :tabIndex="mappingProps.tabIndex"
                        >
                          {{ i18nTranslate(Terms.title.download.ReferenceExpr, '下载') }}
                        </t-button>

                        <!-- <Icon
                          name2="delete"
                          name="fas dx-icon icon-t-delete-outlined"
                          class="primary-color pointer font-size-standard"
                          size="14px"
                          alt="删除"
                          @click="deleteLine(props.row)"
                          :tabIndex="mappingProps.tabIndex"
                        ></Icon> -->
                        <t-button
                          icon="fas dx-icon icon-t-delete-outlined"
                          label=""
                          class="tr-button-icon-text pointer font-size-standard"
                          @click="deleteLine(props.row)"
                          :tabIndex="mappingProps.tabIndex"
                        />
                      </div>
                    </t-td>
                  </template>
                  <template v-slot:body-cell-FailedCount="props">
                    <t-td :props="props">
                      <div
                        class="error-line"
                        :class="props.row.FailedCount ? 'canView' : ''"
                        @click="
                          props.row.FailedCount
                            ? viewDetai(props.row)
                            : () => {}
                        "
                      >
                        <!-- <span class="error-line-button" :tabIndex="mappingProps.tabIndex">{{ props.row.FailedCount }} </span> -->
                        <t-button
                          class="button-span pointer font-size-standard tr-button-text error-line-button"
                          :tabIndex="mappingProps.tabIndex"
                        >{{ props.row.FailedCount }} </t-button>
                      </div>
                    </t-td>
                  </template>
                </Table>
              </template>
              <template v-else>
                <div class="table-placeholder">
                  <no-data-placeholder :noData="i18nTranslate(Terms.title.noData.ReferenceExpr, '暂无数据')"></no-data-placeholder>
                </div>
              </template>
            </t-tab-panel>
            <t-tab-panel :name="1">
              <div class="func-line">
                <p class="tips">{{ tipsWord }}</p>
                <div class="button-group">
                  <t-button
                    :disabled="!(rowsEx && rowsEx.length && rowsEx.length > 0)"
                    icon="fas dx-icon icon-t-delete-outlined"
                    :label="i18nTranslate(Terms.title.clearnExportTask.ReferenceExpr, '清空导出任务')"
                    class="tr-button-default"
                    align="left"
                    @click="clearnExportList"
                    :tabIndex="mappingProps.tabIndex"
                  ></t-button>
                  <!-- <Icon
                    name="refresh"
                    class="custom-icon-refresh"
                    color="primary"
                    alt="刷新"
                    @click="getTaskList('Refresh')"
                    @keyup.enter="getTaskList('Refresh')"
                    @keyup.space="getTaskList('Refresh')"
                    :tabIndex="mappingProps.tabIndex"
                  /> -->
                  <t-button
                    icon="refresh"
                    label=""
                    class="tr-button-icon-text custom-icon-refresh"
                    @click="getTaskList('Refresh')"
                    :tabIndex="mappingProps.tabIndex"
                  />
                </div>
              </div>
              <template v-if="rowsEx && rowsEx.length && rowsEx.length > 0">
                <template
                  v-if="false"
                  alt="注释: flagcomment 导出任务 列表"
                ></template>
                <Table
                  :rows="rowsEx"
                  :columns="columnsEx"
                  row-key="ID"
                  flat
                  class="my-sticky-column-table"
                  v-model:pagination="pagination"
                  @request="onRequest"
                  :rows-per-page-options="rowsPerPageOptions"
                  :tabIndex="mappingProps.tabIndex"
                >
                  <template v-slot:body-cell-State="props">
                    <t-td :props="props">
                      <div @click="handleClickState(props)">
                        <!-- <Icon
                          v-show="props.row.State === 0"
                          title="加载中"
                          color="orange"
                          name="schedule"
                          size="18px"
                        /> -->
                        <SpinnerIos
                          v-show="props.row.State === 0"
                          title="加载中"
                          color="orange"
                          size="18px"
                        />
                        <Icon
                          v-show="props.row.State === 1"
                          title="成功"
                          color="green"
                          name="done"
                          name2="check_circle_outline"
                          size="18px"
                        />
                        <Icon
                          v-show="props.row.State === 2"
                          :title="i18nTranslate(Terms.title.failTips.ReferenceExpr, '失败')"
                          color="red"
                          name="close"
                          name2="close_circle_outline"
                          size="18px"
                        />
                      </div>
                    </t-td>
                  </template>
                  <template v-slot:body-cell-FileName="props">
                    <t-td :props="props">
                      <div class="file-name-line">
                        <span
                          @click="previewFile(props.row)"
                          :class="getDownLoadCss(props.row, previewFileEnable)"
                        >
                          {{ props.row.FileName }}
                        </span>
                        <t-button
                          @click="downExportloadExcel(props.row)"
                          class="button-span primary-color pointer font-size-standard tr-button-text"
                          :class="getDownLoadCss(props.row, true)"
                          style="margin-left: 20px"
                          :tabIndex="mappingProps.tabIndex"
                        >
                          {{ i18nTranslate(Terms.title.download.ReferenceExpr, '下载') }}
                        </t-button>
                      </div>
                    </t-td>
                  </template>
                  <template v-slot:body-cell-Operation="props">
                    <t-td :props="props">
                      <div>
                        <t-button
                          icon="fas dx-icon icon-t-delete-outlined"
                          label=""
                          class="tr-button-icon-text pointer font-size-standard"
                          @click="deleteExportLine(props.row)"
                          :tabIndex="mappingProps.tabIndex"
                        />
                      </div>
                    </t-td>
                  </template>
                </Table>
              </template>
              <template v-else>
                <div class="table-placeholder">
                  <no-data-placeholder :noData="i18nTranslate(Terms.title.noData.ReferenceExpr, '暂无数据')"></no-data-placeholder>
                </div>
              </template>
            </t-tab-panel>
          </t-tabs>

        </t-card-section>

        <t-card-actions align="right" class="close-actions">
          <!-- 用第二个，保证 button 的 hover / focus 效果统一 -->
          <!-- <t-button label="关闭" outline @click="dialog = false" /> -->
          <t-button :label="i18nTranslate(Terms.title.close.ReferenceExpr, '关闭')" class="tr-button-default" @click="dialog = false" :tabIndex="mappingProps.tabIndex"/>
        </t-card-actions>
      </t-card>
    </t-dialog>
    <t-dialog v-model:show="dialogSheet" class="t-import-export-dialog">
      <t-card style="width: 500px; max-width: 500px" class="dialog-wrap">
        <t-card-section class="row items-center q-pb-none dialog-title">
          <div class="">{{ i18nTranslate(Terms.notify.exportMessage.ReferenceExpr, '是否要执行') }} {{ RowNum }} {{ i18nTranslate(Terms.notify.exportMessage1.ReferenceExpr, '条数据的导入') }}?</div>
          <t-space />
          <t-button icon="close" class="tr-button-icon-text font-size-standard" :tabIndex="mappingProps.tabIndex" @click="dialogSheet = false"/>
        </t-card-section>

        <t-card-section class="sheet-card-section">
          <div class="sheet-card-section-text" :title="SheetName">{{ i18nTranslate(Terms.title.import.ReferenceExpr, '导入') }} {{ SheetName }} </div>
          <Select v-model="SheetName" :options="sheetList" class="sheet-card-section-select" :tabIndex="mappingProps.tabIndex"></Select>
          <t-space />
        </t-card-section>

        <t-card-actions class="sheet-card-section-button-line" align="right">
          <!-- color="primary" -->
          <t-button class="tr-button-default" :label="i18nTranslate(Terms.title.close.ReferenceExpr, '关闭')" @click="dialogSheet = false" />
          <t-button
            class="tr-button-primary"
            :label="i18nTranslate(Terms.title.confirm.ReferenceExpr, '确定')"
            @click="confirmSheet"
          />
        </t-card-actions>
      </t-card>
    </t-dialog>

    <!-- 本弹窗废弃, 转用 showPopup_checkExporttype2 -->
    <t-dialog v-model:show="dialogEx" class="t-import-export-dialog">
      <t-card class="dialog-wrap">
        <!--
          dialogEx
          改为使用了这个弹窗
          showPopup_checkExporttype
          后来又用了这个弹窗
          showPopup_checkExporttype2
        -->
      </t-card>
    </t-dialog>

    <t-dialog
      v-model:show="showPopup_checkExporttype2"
      class="t-import-export-dialog"
      :class="isMobile ? 't-import-export-dialog-mobile' : ''"
      @hide="handleHideDiaExportAll"
    >
      <t-card style="min-width: 400px; max-width: 1300px" class="dialog-wrap">
        <t-card-section class="row items-center q-pb-none dialog-title">
          <div class="">{{ i18nTranslate(Terms.title.export.ReferenceExpr, '导出') }}</div>
          <t-space />
          <t-button icon="close" class="tr-button-icon-text font-size-standard" :tabIndex="mappingProps.tabIndex" @click="showPopup_checkExporttype2 = false" />
        </t-card-section>
        <t-card-section class="export-all-section">
          <div class="left transfer-panel">
            <p class="transfer-panel__header">
              <label class="checkbox-wrap">
                <div class="checkbox-wrap-left">
                  <t-checkbox size="xs" v-model="leftAllCheck" :tabIndex="mappingProps.tabIndex"></t-checkbox>
                  <span class="checkbox-word">{{ i18nTranslate(Terms.title.optionalField.ReferenceExpr, '可选字段') }}</span>
                </div>
                <div class="checkbox-wrap-right">
                  <span>{{
                    leftList.filter(item => item.checked).length
                  }}</span>
                  <span>/</span>
                  <span>{{ leftList.length }}</span>
                </div>
              </label>
            </p>
            <div class="el-transfer-panel__body">
              <div class="transfer-panel__filter">
                <t-input
                  v-model="leftFilter"
                  type="text"
                  clearable
                  prependIcon="search"
                  @input="handleInputLeftFilter"
                  :tabIndex="mappingProps.tabIndex"
                />
              </div>
              <ul id="transfer-panel__list__left" class="transfer-panel__list">
                <li
                  v-for="(item, index) of leftList"
                  :key="item[transferKey]"
                  class="transfer-panel__item"
                >
                  <t-checkbox size="xs" v-model="item.checked" :tabIndex="mappingProps.tabIndex"></t-checkbox>
                  <span class="checkbox__span" :title="item.ExcelColName">{{ item.ExcelColName }}</span>
                </li>
              </ul>
            </div>
          </div>
          <div class="middle">
            <div class="middle-content">
              <!-- color="" 测试了下, 不支持 rgba -- ok 现在 支持了 -->
              <t-button
                :icon="`${TComponents?.IconList?.common??'fas dx-icon'} ${TComponents?.IconList?.arrowRight??'icon-t-arrow-right'}`"
                :disabled="!leftList?.find(item => item.checked)"
                :color="
                  !leftList?.find(item => item.checked)
                    ? `rgba(0,0,0,.32)`
                    : `rgba(0,0,0,.9)`
                "
                outline
                size="12px"
                class="tr-button-icon-default transfer-button"
                @click="
                  handleToRight();
                  handleChange();
                "
              ></t-button>
              <t-button
                :icon="`${TComponents?.IconList?.common??'fas dx-icon'} ${TComponents?.IconList?.arrowLeft??'icon-t-arrow-left'}`"
                :disabled="!rightList?.find(item => item.checked)"
                :color="
                  !rightList?.find(item => item.checked)
                    ? `rgba(0,0,0,.32)`
                    : `rgba(0,0,0,.9)`
                "
                outline
                size="12px"
                class="transfer-button"
                @click="handleToLeft"
              ></t-button>
            </div>
          </div>
          <div class="right transfer-panel">
            <p class="transfer-panel__header">
              <label class="checkbox-wrap">
                <div class="checkbox-wrap-left">
                  <t-checkbox size="xs" v-model="rightAllCheck" :tabIndex="mappingProps.tabIndex"></t-checkbox>
                  <span class="checkbox-word">{{ i18nTranslate(Terms.title.exportField.ReferenceExpr, '导出字段') }}</span>
                </div>
                <div class="checkbox-wrap-right">
                  <span>{{
                    rightList.filter(item => item.checked).length
                  }}</span>
                  <span>/</span>
                  <span>{{ rightList.length }}</span>
                </div>
              </label>
            </p>
            <div class="el-transfer-panel__body">
              <div class="transfer-panel__filter">
                <t-input
                  v-model="rightFilter"
                  type="text"
                  clearable
                  prependIcon="search"
                  @input="handleInputRightFilter"
                  :tabIndex="mappingProps.tabIndex"
                />
              </div>
              <ul id="transfer-panel__list__right" class="transfer-panel__list">
                <li
                  v-for="(item, index) of rightList"
                  :key="item[transferKey]"
                  class="transfer-panel__item"
                >
                  <t-checkbox size="xs" v-model="item.checked" :tabIndex="mappingProps.tabIndex"></t-checkbox>
                  <span class="checkbox__span" :title="item.ExcelColName">{{ item.ExcelColName }}</span>
                </li>
              </ul>
            </div>
          </div>
        </t-card-section>

        <t-card-actions align="right">
          <t-button :label="i18nTranslate(Terms.notify.cancel.ReferenceExpr, '取消')" outline class="tr-button-default" @click="showPopup_checkExporttype2 = false" :tabIndex="mappingProps.tabIndex"/>
          <t-button
            :label="i18nTranslate(Terms.title.exportAll.ReferenceExpr, '导出全部数据')"
            class="tr-button-primary"
            @click="
              handleChange();
              exportData('all');
            "
            :tabIndex="mappingProps.tabIndex"
          />
        </t-card-actions>
      </t-card>
    </t-dialog>

    <!-- 本弹窗废弃 改用 showPopup_checkExporttype2 手写的穿梭框 -->
    <t-dialog
      v-model:show="showPopup_checkExporttype"
      class="t-import-export-dialog"
    >
      <t-card style="min-width: 400px; max-width: 1300px" class="dialog-wrap">
        <t-card-section class="row items-center q-pb-none dialog-title">
          <div class="">导出</div>
          <t-space />
          <t-button icon="close" flat round dense @close="showPopup_checkExporttype = false" />
        </t-card-section>

        <t-card-section class="row items-center">
          <div
            ref="exSelectTableWrap"
            id="exSelectTableWrap"
            class="ex-select-table-wrap"
          >
            <!-- <el-transfer ref="transfer" v-model="value" :data="data" /> -->

            <!-- v-model:selected="selected" => checkExportList -->
            <Table
              class="ex-select-table"
              v-model:selected="checkExportList"
              :rows="rowsExDia"
              :columns="columnsExKey"
              row-key="ExcelColName"
              :selected-rows-label="getSelectedString"
              selection="multiple"
              :pagination="{ rowsPerPage: rowsExDia.length }"
              @selection="handleSelection"
              hide-bottom
              :tabIndex="mappingProps.tabIndex"
            >
              <!-- <div class="q-mt-md">
                Selected: {{ JSON.stringify(selected) }}
              </div> -->
            </Table>
          </div>
        </t-card-section>

        <t-card-actions align="right">
          <t-button label="取消" outline @close="showPopup_checkExporttype = false" />
          <t-button
            label="导出全部数据"
            color="primary"
            @click="
              handleChange();
              exportData('all');
            "
            :tabIndex="mappingProps.tabIndex"
          />
        </t-card-actions>
      </t-card>
    </t-dialog>

    <t-dialog v-model:show="showFailTasklistPopup" class="t-import-export-dialog">
      <t-card style="max-width: 1300px" class="dialog-wrap">
        <t-card-section class="row items-center q-pb-none dialog-title">
          <div class="">{{ i18nTranslate(Terms.title.importException.ReferenceExpr, '导入异常')}}</div>
          <t-space />
          <t-button icon="close" class="tr-button-icon-text font-size-standard" :tabIndex="mappingProps.tabIndex" @click="showFailTasklistPopup = false" />
        </t-card-section>

        <t-card-section class="row items-center">
          <div class="">
            <!-- 复制的冗余代码，顺手删除 v-model:selected="checkExportList" -->
            <Table
              :rows="failTasklist"
              :columns="columnsFalil"
              row-key="ID"
              :selected-rows-label="getSelectedString"
              flat
              hide-bottom
              :pagination="{ rowsPerPage: failTasklist.length }"
              :tabIndex="mappingProps.tabIndex"
            >
              <!-- <div class="q-mt-md">
                Selected: {{ JSON.stringify(selected) }}
              </div> -->
            </Table>
          </div>
        </t-card-section>

        <!-- <t-card-actions align="right">
          <t-button flat label="关闭" color="primary" v-close-popup />
        </t-card-actions> -->
      </t-card>
    </t-dialog>
  </div>
</template>

<script setup>
// import moreProps from '../moreProps.js';
import { useQuasar } from '@teld/q-components';
// 这两个时很基本+未二次修改的样式, 直接引用 Quasar，节省体积
import { SpinnerIos } from '../spinner';
import TCard from 't/basic/card';
import TCardSection from 't/basic/card/CardSection';
import TCardActions from 't/basic/card/CardActions';
// import QDialog from '@teld/q-components/Dialog';
import TDialog from 't/basic/dialog';
import _ from 'lodash';
import Sortable from 'sortablejs';
import useMappingProps from 't/common/hooks/useMappingProps';
import { commonProps } from 't/common/utils';
import { Terms, TermsTranslated } from "./Term";
import {
computed,
inject,
nextTick,
onMounted,
reactive,
ref,
useAttrs,
useSlots,
watch
} from 'vue';
import TButton from 't/basic/button';
import ButtonDropdown from '../button-dropdown';
// import ButtonDropdown from '@teld/q-components/ButtonDropdown';
import TCheckbox from '../checkbox';
import Icon from '../icon';
import Item from '../item';
import ItemLabel from '../item-label';
import ItemSection from '../item-section';
import LabelPrefixWraper from '../label-prefix-wraper';
import List from '../list';
// import Table from '@teld/q-components/Table';
// t 层的 table 多了自定义的 paginationLabel 属性，比较好看 --> 显示 1 到100 行，共 527 行
import Table from '../table';
import Select from '../select';
// import Select from '@teld/q-components/select';
// import Tabs from '@teld/q-components/Tabs';
import TTabs from 't/basic/tabs';
import TSpace from 't/basic/space';
import TTabPanel from 't/basic/tab-panel';
import TTd from 't/basic/table/Td';
import TAvatar from 't/basic/avatar';
import NoDataPlaceholder from './components/no-data-placeholder.vue';
import { onUnmounted } from 'vue';
const $q = useQuasar();
const refComponent = ref();
const slots = useSlots();
const attrs = useAttrs();
const isMobile = computed(() => $q.screen.xs || $q.platform.is.mobile)
const executeScript = inject('executeScript');
const LocalVars = inject('LocalVars');
const Widget = inject('Widget');
// const Funcs = inject('Funcs'); // Funcs 不要重写，且不能重写
// 国际化词条
const Funcs = window.Funcs || {
  GetTerms: (c, n) => n,
};
// i18nTranslate 额外转换一层, 针对组件中固定的文本 -- 方便之后将 Funcs.GetTerms 替换成 $q.lang 的形式
const i18nTranslate = (entry, defaultVal) => Funcs.GetTerms(entry, defaultVal);
const executeScriptEx = async param => {
  let result = ''
  if (/^return/.test(param.trim())) {
    result = executeScript(param);
  } else {
    result = await executeScript('return ' + param);
  }
  return result
}
const sheet = ref('1');
// 生命周期：组件挂载
onMounted(() => {
  window.executeScript = executeScript;
});
const props = defineProps({
  ...commonProps,
  ...LabelPrefixWraper.props,
  ...ButtonDropdown.props,
  visible: {
    type: Boolean,
    default() {
      return true
    }
  },
  // ...moreProps,
  instanceCode: {
    type: String,
    default() {
      return '';
    },
  },
  beforeImportJSScript: {
    type: String,
    default() {
      return '';
    },
  },
  beforeExportJSScript: {
    type: String,
    default() {
      return '';
    },
  },
  importConfig: {
    type: [Object, String],
    default() {
      return null;
    },
  },
  exportConfig: {
    type: [Object, String],
    default() {
      return null;
    },
  },
  exportConfigMore: {
    type: Object,
    default() {
      return null; // 可能包含这两个参数: { AdvancedFilter, AdvancedSort, FasDynamicFilter } // 存在则会 覆盖原有的接口入参数
    },
  },
  importBtnName: {
    type: String,
    default: '导入', // 元数据的默认值 与此相同
  },
  exportBtnName: {
    type: String,
    default: '导出', // 元数据的默认值 与此相同
  },
  exportFileName: {
    type: String,
    default: '',
  },
  // 低代码传入的是 tabIndex，而非 tabindex, 就是为了覆盖前者
  tabIndex: {
    type: [String, Number],
    default() {
      return 1;
    },
  },
});
// == emit ==
const emit = defineEmits([
  'click',
  'beforeImport',
  'afterImport',
  'beforeExport',
  'afterExport',
  // 'update:dialog',
  // 'update:dialogEx',
  // 'update:dialogSheet',
  // 'update:SheetName',
  // 'update:tab',
]);
// 原来的出码用到的 Props - start
// showPopup -- 老代码的变量名 - "任务列表"弹窗
const rowsPerPageOptions = [10, 20, 50, 100, 150, 500, 1000]
const dialog = ref(false);
const dialogEx = ref(false);
const showPopup_checkExporttype = ref(false);
const showPopup_checkExporttype2 = ref(false);
const dialogSheet = ref(false); // dialogVisibleTip 旧版本字段
const showFailTasklistPopup = ref(false);
const tab = ref(0); // modify
const tabsComp = ref(null);
const dialogMissionList = ref(null);
const tabList = computed(() => {
  //  (*1) 不能用此处，解释 见 下一个个 (*1)
  // const arr = [];
  // if (mappingProps.importConfig) arr.push({ label: '导入任务', code: 0 });
  // if (mappingProps.exportConfig) arr.push({ label: '导出任务', code: 1 });

  // i18n 前，变为
  // const arr = [
  //   { label: '导入任务', code: 0 },
  //   { label: '导出任务', code: 1 },
  // ];
  // i18n 后，变为
  const arr = [
    { label: Funcs.GetTerms('Schema.Controls.export_import.Terms.title.importTask', '导入任务') || '导入任务', code: 0 },
    { label: Funcs.GetTerms('Schema.Controls.export_import.Terms.title.exportTask', '导出任务') || '导出任务', code: 1 },
  ];
  return arr;
});
const handleHideDiaExportAll = () => {
  leftFilter.value = '';
  rightFilter.value = '';
};
// 穿梭框 - transfer - quasar - custorm
// 若封装成独立组件则,
// 暴露给外部的参数为, data => basicList, key => transferKey, v-model => "rightKeys"
const basicList = ref([
  // { key: 1, checked: false, ColName: 'name' },
  // { key: 2, checked: false, ColName: 'modifier' },
  // { key: 3, checked: false, ColName: 'time' },
  // { key: 4, checked: false, ColName: 'creator' },
]);
const transferKey = ref('ColName'); // default - 'key' // flagok 此处可清除默认值, 打开弹窗时会赋值
const rightKeys = ref([
  // 'time', 'creator'
]);
// 若封装成独立组件则,
// 内部使用的参数为
const leftFilter = ref('');
const rightFilter = ref('');
const leftList = computed(() => {
  if (!leftFilter.value) {
    return basicList.value.filter(
      item => !rightKeys.value.includes(item[transferKey.value]),
    );
  } else {
    return basicList.value.filter(
      item =>
        !rightKeys.value.includes(item[transferKey.value]) &&
        item.ExcelColName.includes(leftFilter.value),
    );
  }
});
const rightList = computed(() => {
  if (!rightFilter.value) {
    return basicList.value.filter(item =>
      rightKeys.value.includes(item[transferKey.value]),
    );
  } else {
    return basicList.value.filter(
      item =>
        rightKeys.value.includes(item[transferKey.value]) &&
        item.ExcelColName.includes(rightFilter.value),
    );
  }
});
const leftAllCheck = computed({
  get() {
    return handleCheckAll(leftList.value);
  },
  set(val) {
    if (val) leftList.value.forEach(item => (item.checked = true));
    else leftList.value.forEach(item => (item.checked = false));
  },
});
const rightAllCheck = computed({
  get() {
    return handleCheckAll(rightList.value);
  },
  set(val) {
    if (val) rightList.value.forEach(item => (item.checked = true));
    else rightList.value.forEach(item => (item.checked = false));
  },
});
const handleCheckAll = array => {
  if (array?.length > 0) {
    const allFill = array.every(item => item.checked === true);
    const allBlank = array.every(item => item.checked === false);
    if (allFill) return true;
    else if (allBlank) return false;
    else return null;
  }
  return false;
};
const handleToRight = () => {
  leftList.value.forEach(item => {
    if (item.checked) {
      rightKeys.value.push(item[transferKey.value]);
      item.checked = false;
    }
  });
  // 排个序
  handleSortRightKeys();
};
const handleSortRightKeys = () => {
  rightKeys.value = rightList.value.map(item => item.ColName);
  expoetDataValue.value = rightKeys.value;
};
const handleToLeft = () => {
  rightList.value.forEach(item => {
    if (item.checked) {
      const index = rightKeys.value.findIndex(
        atom => atom === item[transferKey.value],
      );
      rightKeys.value.splice(index, 1);
      item.checked = false;
    }
  });
};
const handleInputLeftFilter = val => {
  console.log('input', val);
};
const handleInputRightFilter = val => {
  console.log('input', val);
};
// ** new
const handleListenTabs = el => {
  tabsComp.value = el;
  // 没有 导入任务列表 的tab不展示 // 不能用 tabList 控制 见 (*1), 这个会使得 tab 的默认值不正确
  nextTick(() => {
    // if (!mappingProps.importConfig)
    //   document.querySelectorAll(
    //     '.dialog-mission-list .q-tabs__content .q-tab',
    //   )[0].style.display = 'none';
    // if (!mappingProps.exportConfig)
    //   document.querySelectorAll(
    //     '.dialog-mission-list .q-tabs__content .q-tab',
    //   )[1].style.display = 'none';

    // 只有一个 tab 就不要展示 tabs 行了 -- 2024.05.09 修改（昨晚评审会）
    if (!mappingProps.importConfig || !mappingProps.exportConfig) {
      document.querySelector('.dialog-mission-list .tabs-wrap').style.display = 'none';
      // 当没有 tabs 了，保证距离头部 还是 26px; 左右对齐
      document.querySelector('.dialog-mission-list .card-section-content').style['padding-top'] = '3px';
      document.querySelector('.dialog-mission-list .q-tab-panels').style['padding-left'] = '0px';
      document.querySelector('.dialog-mission-list .q-tab-panels').style['padding-right'] = '0px';
    }
  });
};
const previewFileEnable = ref(window.PreviewFileEnable); // 迁移, 原来是 首字母小写 window.previewFileEnable => 现在约定-全局变量的首字母大写
const expoetDataValue = ref([]); // ['ID', 'Name', 'Creator' ...]
const checkExportList = ref([]); // [{}, {}, {}, ...]
// 导出 弹窗 - 导出全部数据 时用到
const rowsExDia = ref([]); // computed(() => { return exportConfigComputed.value.Columns; });
const selected = ref([]);
// 删除 确认 弹窗
// 用不到transfer了，换插件了/换写法了 // const transfer = ref(null);
const exSelectTableWrap = ref(null);

const columnsExKey = ref([
  {
    name: 'ExcelColName',
    align: 'left',
    label: '可选字段',
    field: 'ExcelColName',
    autoWidth: true,
  },
]);
// :selected-rows-label="getSelectedString" 属性没有的话，
// 默认展示 已选择n行 -- 这里给他置空
const getSelectedString = () => {};
const handleSelection = details => {
  const ColName = details?.rows[0]?.ColName;
  const { added } = details;
  nextTick(() => {
    const arr = [];
    rowsExDia.value.forEach(item => {
      if (!!checkExportList.value.find(atom => atom.ColName === item.ColName)) {
        item.isShow = true;
        arr.push(item);
      } else {
        item.isShow = false;
      }
    });
    checkExportList.value = arr;
    expoetDataValue.value = arr.map(item => item.ColName);
  });
};

const handleClickTab = val => {
  const oldValue = tab.value;
  if (tabsComp?.value) tab.value = tabsComp.value.currentTabIndex;
  if (oldValue !== tab.value) GetImportTaskList();
};
// const handleChangeTab = e => {
// console.log('eee', e)
// tab = e;
// GetImportTaskList();
// };
// ** new end
// 导入
const handleImport = (keyboard) => {
  upload.value.click();
  // 选完后，触发 input 的 change 事件
  // getFile -> getImportFile
};
// 导入选完文件时
const getImportFile = async (e, val, data) => {
  // 第一部分 - 制作数据
  retryJson.value = data;
  // 导入事件
  let file = e.target.files[0];
  let realfile = await getBase64(file);
  realfile = realfile.split(',')[1];
  let params = {
    Data: realfile,
    Extension: file.name.split('.').pop(),
    Name: file.name,
    PathId: '101',
  };
  // 第二部分 - 调用请求
  var xhr = new XMLHttpRequest();
  // 请求地址 demo
  // http: + //resource.teld.cc + /api/resource/uploaddoc
  // 迁移, window.ResourcePath => window.TeldWebConfig.ResourceURL
  xhr.open(
    'POST',
      window.TeldWebConfig.ResourceURL.startsWith('http') ?
      (window.TeldWebConfig.ResourceURL +
        '/api/resource/uploaddoc') :
      (window.location.protocol +
      window.TeldWebConfig.ResourceURL +
      '/api/resource/uploaddoc'),
    false,
  );
  // 添加http头，发送信息至服务器时内容编码类型
  xhr.setRequestHeader('X-Token', getCookie('telda'));
  xhr.setRequestHeader('SRC', 'WEB');
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.onreadystatechange = async () => {
    if (xhr.readyState == 4) {
      if (xhr.status == 200 || xhr.status == 304) {
        var response;
        if (typeof xhr.responseText == 'string') {
          try {
            response = JSON.parse(xhr.responseText);
          } catch (error) {
            response = {};
          }
        } else {
          response = xhr.responseText;
        }
        // 上传文件成功后
        importConfirmation(response.RelativeUrl, file.name, val);
      } else if (xhr.status == 401) {
      }
    }
    uplaodFile.value = false;
    uploadFile2.value = false;
    nextTick(() => {
      uplaodFile.value = true;
      uploadFile2.value = true;
    });
  };
  xhr.send(JSON.stringify(params));
};
// 导入文件时，暂存的重试数据
const retryJson = ref({});
// 导入文件时，用到的 input 的 显示隐藏属性 -- ps: 迁移发现，uplaodFile 拼写错误，先这样
const uplaodFile = ref(true);
const uploadFile2 = ref(true);

// 导入文件有多个 sheet 时，用到的选择参数
const SheetName = ref('');
const sheetList = ref([]);

// 导出2
const handleExport2 = () => {
  if (!checkDQ()) {
    return;
  }
  showPopup_checkExporttype2.value = true;
  nextTick(() => {
    expoetDataValue.value = [];
    checkExportList.value = [];

    rowsExDia.value = _.cloneDeep(exportConfigComputed.value?.Columns);
    // 使用新封装的 quasar-transfer 的变量, 这样改动最小, 且方便之后提取成公共组件
    basicList.value = rowsExDia.value;
    basicList.value.forEach(item => (item.checked = false));
    transferKey.value = 'ColName';
    rightKeys.value = expoetDataValue.value;

    // 迁移, 注释, mounted那段可以去掉，因为每次打开弹窗的时候都会执行一遍 （ 导入 btn -> 弹窗 -> 选择导出字段 ) -- 重置排序
    // exportConfigComputed.value?.Columns?.map(val => {
    rowsExDia.value?.map(val => {
      if (val.isShow) {
        expoetDataValue.value.push(val.ColName);
        checkExportList.value.push(val);
      }
    });
    // == 操作穿梭框 + 排序 ==
    // 主要是 Sortable.create() + handleChange();
    const el = document.getElementById('transfer-panel__list__right');
    Sortable.create(el, {
      onEnd: evt => {
        const { oldIndex, newIndex } = evt;
        const oldIndexInBaiscList = basicList.value.findIndex(
          item => item.ColName === rightList.value[oldIndex].ColName,
        );
        // const newIndexInBasicList = oldIndexInBaiscList - oldIndex + newIndex;
        const newIndexInBasicList = basicList.value.findIndex(
          item => item.ColName === rightList.value[newIndex].ColName,
        );
        // 此处改为调整 basicList 的顺序, 其他的会计算（computed) 出来, 再给 rightKeys 排一下顺序 -- 因为 组件的 rightKeys 是无序的
        const one = basicList.value.splice(oldIndexInBaiscList, 1);
        if (!one || one === 'undefined') return;
        basicList.value.splice(newIndexInBasicList, 0, one[0]);
        handleSortRightKeys();
        handleChange();
      },
    });
  });
};
const checkDQ = () => {
  // if (!exportConfigComputed.value?.DataSource?.ActionID) {
  if (!exportConfigComputed.value.DataSource.ActionID) {
    // $q.notify({
    //   closeBtn: true,
    //   type: 'warning',
    //   position: 'bottom-right',
    //   message: `导出控件配置不完整，请选择DQ`, // Funcs.GetTerms('Schema.Controls.export_import.Terms.title.checkDQ', '导出控件配置不完整，请选择DQ')
    // });
    // i18n + 公共消息提示
    Funcs.Notify(TermsTranslated.title.notify, TermsTranslated.title.checkDQ, 'warning');

    // 下方文案写错了，应该是用下下方的 flagok
    // Terms.title.checkCdo => 导入控件配置不完整，请选择CDO
    // Funcs.Notify(Terms.title.notify, Terms.title.checkCdo, 'warning');

    // this.$message({
    //   message: " 导出控件配置不完整，请选择DQ",
    //   type: "warning",
    //   showClose: true,
    // });
    return false;
  }
  return true;
  // 导入导出控件配置不完整，请选择cdo、DQ
};
// 迁移, 注释, checkExportList 按照 expoetDataValue 中的顺序排序
// 迁移, handleChange 是原来的名字, 建议改成 handleFormatExportListByKeys
// 另外, expoetDataValue 变量 可以替换为新组件 的 rightKeys, checkExportList 变量 可以直接用新组件 的 rightList （ 涉及到的变量太多, 暂不替换, 通过 expoetDataValue.value = rightKeys.value 或 rightKeys.value =expoetDataValue.value 等将两个变量的引用 指向一处 )
// 新组件中, rightList 直接是有序的, 直接用 rightList => 得到 有序的 rightKeys
const handleChange = () => {
  let arr = [];
  expoetDataValue.value?.map(item => {
    // exportConfigComputed.value?.Columns?.map(val => {
    rowsExDia.value.map(val => {
      if (item == val.ColName) {
        val.isShow = true;
        arr.push(val);
      }
    });
  });
  checkExportList.value = JSON.parse(JSON.stringify(arr));
};
// 迁移, 本行, 未改方法名, 方便查找老代码
const exportData = async type => {
  let Jsparams = {};
  emit('beforeExport', Jsparams);

  //如果传入cancel 终止当前操作
  if (Jsparams.hasOwnProperty('cancel') && Jsparams.cancel) {
    showPopup_checkExporttype2.value = false;
    return;
  }
  let instanceCode = mappingProps.instanceCode;
  let JSScript = mappingProps.beforeExportJSScript;
  let hasFunction = true;
  let isNot = false;
  if (JSScript.indexOf('.' + instanceCode + '.export2') != -1) {
    let JSScriptArr = JSScript.split('\n');
    JSScriptArr.forEach(item => {
      if (item.indexOf('.' + instanceCode + '.export2') != -1) {
        let Params = item.split(';');
        let index = Params.findIndex(
          item => item.indexOf('.' + instanceCode + '.export2') != -1,
        );

        if (
          Params[index] &&
          (Params[index].indexOf('*') != -1 ||
            Params[index].indexOf('//') != -1)
        ) {
          hasFunction = false;
        } else {
          isNot = true;
        }
      }
    });
  } else {
    hasFunction = false;
  }
  if (hasFunction || isNot) {
  } else {
    export2(type);
  }
};

const export2 = async type => {
  let importDefs = _.cloneDeep(checkExportList.value);
  // 上面 可用这个值验证下 _.cloneDeep(checkExportList.value);
  if (importDefs.length == 0) {
    // i18n
    Funcs.Notify(TermsTranslated.title.notify, TermsTranslated.title.choiseExportData, 'warning');
    // $q.notify({
    //   closeBtn: true,
    //   type: 'warning',
    //   position: 'bottom-right',
    //   message: `请选择导出字段`, // Funcs.GetTerms('Schema.Controls.export_import.Terms.title.choiseExportData', '请选择导出字段')
    // });
    return;
  }
  var parameters = [];

  if (exportConfigComputed.value.DataSource.Parameters) {
    var Parameters = JSON.parse(
      JSON.stringify(exportConfigComputed.value.DataSource.Parameters),
    );
    await Promise.all(
      Parameters.map(async (item, index) => {
        if (
          type == 'all' &&
          (item.ParameterName == 'PageSize' ||
            item.ParameterName == 'PageIndex' ||
            ['FasPageCount', 'FasPageIndex'].includes(
              item.ParameterName,
            )) /** 2022年12月12日 多维视图集成导出功能 */
        ) {
          item.ParameterValue = 0;
        }
        // 2024.3.25 对接 多维视图
        // 多维视图中，会透传 exportConfigMore - AdvancedFilter AdvancedSort，两个参数，有的话，就覆盖掉
        if (
          item.ParameterName === 'AdvancedFilter' &&
          mappingProps?.exportConfigMore?.AdvancedFilter
        ) {
          item.ParameterValue = mappingProps.exportConfigMore.AdvancedFilter;
        }
        if (
          item.ParameterName === 'AdvancedSort' &&
          mappingProps?.exportConfigMore?.AdvancedSort
        ) {
          item.ParameterValue = mappingProps.exportConfigMore.AdvancedSort;
        }
        if (
          item.ParameterName === 'FasDynamicFilter' &&
          mappingProps?.exportConfigMore?.FasDynamicFilter
        ) {
          item.ParameterValue = mappingProps.exportConfigMore.FasDynamicFilter;
        }
        // 2024.3.25 对接 多维视图 end
        /** 2022年12月12日 多维视图集成导出功 */
        if (item.ParameterName == 'mixedView.Skip') {
          // mixedView.Skip - 多维视图的 一个标志吗？
          // 迁移, 执行代码的函数 -- 全局替换 window.TeldFasRTUtils.expression.execute => Funcs.Eval
          // Funcs.Eval(item.ParameterValue);
          // 改为 executeScript() // flagok 其他地方也要改
          // item.ParameterValue
          if (/^return/.test(item.ParameterValue.trim()))
            executeScript(item.ParameterValue);
          else executeScript('return ' + item.ParameterValue);
          return;
        }
        let ParameterValue = item.ParameterValue;
        if (item.ParameterValue) {
          if (/^return/.test(item.ParameterValue.trim())) {
            ParameterValue = executeScript(item.ParameterValue);
            // alert('ParameterValue' + ParameterValue)
          } else {
            ParameterValue = await executeScript('return ' + item.ParameterValue);
            // alert('ParameterValue - yes - ' + ParameterValue)
          }
        }
        /** END 2022年12月12日 多维视图集成导出功 */
        // advancedFilter advancedSort
        parameters.push({
          Order: index,
          ParamType: item.ParamType,
          ParameterName: item.ParameterName,
          //执行变量
          // ParameterValue: item.ParameterValue
          //   ? executeScript(item.ParameterValue).result
          //   : item.ParameterValue,
          ParameterValue,
        });
      })
    )
  }

  // // 排序
  let tempImportDefs = [];
  expoetDataValue.value.map(item => {
    importDefs.map(val => {
      if (item == val.ColName) {
        val.isShow = true;
        tempImportDefs.push(val);
      }
    });
  });
  tempImportDefs.forEach(item => {
    if (item.Mapping) {
      item.Mapping.forEach(item_mapping => {
        if (item_mapping.valueReferenceExpr) {
          // 代码, 迁移, 这个 Funcs.GetTerms 不用转换
          item_mapping.text = Funcs.GetTerms(
            item_mapping.valueReferenceExpr,
            item_mapping.text,
          );
        }
      });
    }
  });
  //
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-ExportData'),
      ),
      type: 'post',
      data: {
        parameters: JSON.stringify(parameters),
        exportDefs: JSON.stringify(tempImportDefs),
        exportParam: JSON.stringify({
          MetaDataID: exportConfigComputed.value.DataSource.ActionID, //元数据ID DQ或Action
          ActionType: exportConfigComputed.value.DataSource.ActionType, //Action类型  0Action 1DQ
          ExportType: exportConfigComputed.value.DataSource.ExportType, //导出类型 0普通导出 1报表导出
          Type: type == 'all' ? 1 : 0, //分页类型 0导出全部 1导出当前页
          MaxRow: exportConfigComputed.value.MaxRows,
          FileName:mappingProps.exportFileName
        }),
      },
    })
    .then(data => {
      if (data.state == 1) {
        exportInterval.value=0
        showPopup_checkExporttype2.value = false;

        if (dialog.value) {
          dialog.value = false;
        }
        nextTick(() => {
          // 迁移, 优化, 此时 任务列表-dialog 的tab 应该切换到 导出列表
          tab.value = 1; // q-tabs 用
          // alert('导出回调')
          GetImportTaskList();
        });
        if (data.state == 1) {
          setTimeout(() => {
            emit('afterExport', { taskID: data.data.ID });
            // 迁移, 注释, 上面这个写法就是和下面等价的
            // self.triggerEventHandler('AfterExport', {
            //   taskID: data.data.ID,
            // });
          }, 1000);
        }
        setTimeout(() => {
          showPopup_checkExporttype2.value = false;
        }, 500);
      }
    })
    .catch(err => {
      // i18n
      // $q.notify({
      //   closeBtn: true,
      //   type: 'warning',
      //   position: 'bottom-right',
      //   message: `添加到导出任务列表失败`,
      // });
      // i18n
      Funcs.Notify(TermsTranslated.title.notify, TermsTranslated.notify.addExportFail, 'warning');

      // self.$message({
      //   message: Terms.notify.addExportFail,
      //   type: "warning",
      //   showClose: true,
      // });
      showPopup_checkExporttype2.value = false;
    });
};
// == 导出相关辅助函数 == end

// 点击 ”导入模板“ 触发 - 会去下载导入模板 （downloadStencil）
const dowmloadTemplate = () => {
  if (!checkCdo()) {
    return;
  }
  let importDefs = [];
  if (importConfigComputed.value.defineDataSocurce) {
    let defineDataSocurce = JSON.parse(
      JSON.stringify(importConfigComputed.value.defineDataSocurce),
    );
    importDefs = defineDataSocurce.filter(item => {
      item.ImportRule = item.ImportRules;
      if (item.Parameters) {
        item.Parameters.map(async j => {
          if (j.ParameterValue) {
            // window.TeldFasRTUtils.expression.execute() 这个方法废弃了, 要用 executeScript() 2024.10.23 处理罗星宇的问题时发现
            // j.ParameterValue = window.TeldFasRTUtils.expression.execute(
            //   j.ParameterValue,
            // ).result;
            if (/^return/.test(j.ParameterValue.trim())) {
              j.ParameterValue = executeScript(j.ParameterValue);
            } else {
              j.ParameterValue = await executeScript('return ' + j.ParameterValue);
            }
          }
          return j;
        });
      }
      return item.isShow;
    });
  }
  //
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-DownloadTemplate'),
      ),
      type: 'post',
      data: {
        cdoID: importConfigComputed.value.CdoSource.Value.ID,
        importDefs: JSON.stringify(importDefs),
        isEnableUniqueCol: importConfigComputed.value.hasOwnProperty(
          'IsEnableUniqueCol',
        )
          ? importConfigComputed.value.IsEnableUniqueCol
          : true,
        isEnableExplainRow: importConfigComputed.value.hasOwnProperty(
          'IsEnableExplainRow',
        )
          ? importConfigComputed.value.IsEnableExplainRow
          : true,
      },
    })
    .then(data => {
      if (data.state == 1) {
        downloadFileByBase64(data.content, data.fileName);
      } else {
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `失败原因：${data.errmsg}`,
        // });
        // i18n
        Funcs.Notify(
          Terms.title.notify,
          `${TermsTranslated.notify.failReason}：${data.errmsg}`,
          'warning',
        );
      }
    });
  //
  //
  //
  //
  // window.getDataAsync(
  //   fasRequestTagAdd(window.FrameSGHost + 'FASR-DownloadTemplate'),
  //   'POST',
  //   {
  //     cdoID: importConfigComputed.value.CdoSource.Value.ID,
  //     importDefs: JSON.stringify(importDefs),
  //     isEnableUniqueCol: importConfigComputed.value.hasOwnProperty(
  //       'IsEnableUniqueCol',
  //     )
  //       ? importConfigComputed.value.IsEnableUniqueCol
  //       : true,
  //     isEnableExplainRow: importConfigComputed.value.hasOwnProperty(
  //       'IsEnableExplainRow',
  //     )
  //       ? importConfigComputed.value.IsEnableExplainRow
  //       : true,
  //   },
  //   function (data) {
  //     if (data.state == 1) {
  //       downloadFileByBase64(data.content, data.fileName);
  //     } else {
  //       Funcs.Notify(
  //         Terms.title.notify,
  //         `${Terms.notify.failReason}：${data.errmsg}`,
  //         'warning',
  //       );
  //     }
  //   },
  // );
};
// 任务列表 - btn
const handleMissionList = () => {
  // alert('handleMissionList-')
  if (mappingProps.exportConfig && !mappingProps.importConfig) tab.value = 1;
  GetImportTaskList(); // 迁移, 来的方法名
};
// 任务列表 - 导入任务 - table 表头
const columnsIm = reactive([
  {
    name: 'State',
    label: i18nTranslate(Terms.title.State.ReferenceExpr, '状态'),
    field: 'State',
    align: 'center',
    sortable: false,
  },
  {
    name: 'FileName',
    label: i18nTranslate(Terms.title.FileName.ReferenceExpr, '文件名'),
    field: 'FileName',
    align: 'left',
    sortable: false,
  },
  {
    name: 'ElapsedSeconds',
    label: i18nTranslate(Terms.title.ElapsedSeconds.ReferenceExpr, '耗时(秒)'),
    field: 'ElapsedSeconds',
    sortable: false,
  },
  {
    name: 'SuccessCount',
    label: i18nTranslate(Terms.title.SuccessCount.ReferenceExpr, '成功行数'),
    field: 'SuccessCount',
    sortable: false,
  },
  {
    name: 'FailedCount',
    label: i18nTranslate(Terms.title.FailedCount.ReferenceExpr, '失败行数'),
    field: 'FailedCount',
    sortable: false,
  },
  {
    name: 'ErrMsg',
    label: i18nTranslate(Terms.title.ExportErrMsg.ReferenceExpr, '失败原因'),
    field: 'ErrMsg',
    align: 'left',
    sortable: false,
  },
  {
    name: 'ImportTime',
    label: i18nTranslate(Terms.title.ImportTime.ReferenceExpr, '导入时间'),
    field: 'ImportTime',
    align: 'left',
    sortable: false,
  },
  {
    name: 'Operation',
    label: i18nTranslate(Terms.title.operation.ReferenceExpr, '操作'),
    field: 'Operation',
    align: 'center',
    sortable: false,
  },
]);
// 任务列表 - 导入任务 - table 数据 // 迁移, 原 ImportTasklist -- flag 记得注释
const rowsIm = ref([
  // {
  //   ID: '5a0cd2d1-8b1d-42bb-bfff-f4654a2a3ea9',
  //   State: 3,
  //   ErrMsg: '列【主键ID】不存在',
  //   FilePath: 'CDO_模版xlsx.xlsx',
  //   FileName: 'CDO_模版xlsx.xlsx',
  //   FileURL: 'telddoc/101/bfd6cfbff4c741bb89fbda7b617889cb.xlsx',
  //   FileSize: '10KB',
  //   Script: '',
  //   SuccessCount: 0,
  //   FailedCount: 2,
  //   ElapsedSeconds: 0.02,
  //   ImportTime: '4分钟前',
  // },
  // { State: 0 },
  // { State: 1 },
  // { State: 2 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
  // { State: 3 },
]);
// 导入异常列表 - 某一个导入任务 的 异常信息列表
const failTasklist = ref([]);
const columnsFalil = reactive([
  {
    name: 'RowNum',
    label: i18nTranslate(Terms.title.RowNum.ReferenceExpr, 'Excel行号'),
    field: 'RowNum',
    align: 'center',
    sortable: false,
  },
  {
    name: 'ErrMsg',
    label: i18nTranslate(Terms.title.ErrMsg.ReferenceExpr, '导入错误信息'),
    field: 'ErrMsg',
    align: 'center',
    sortable: false,
  },
]);
// quasar 的 pagination: { page, rowsPerPage, rowsNumber }
const pageIndex = ref(1); // pagination.page
const pageSize = ref(10); // pagination.rowsPerPage
const totalCount = ref(7); // pagination.rowsNumber
// 这两个参数 - 渲染时不需要了 - 等待验证 (×) -- 2024.4.10结论: totalCount 还是需要的， totalPage 不需要了
const totalPage = ref(0);
const pagination = computed(() => {
  return {
    page: pageIndex.value,
    rowsPerPage: pageSize.value,
    rowsNumber: totalCount.value
  }
})

// 任务列表 - 导入任务 - table 数据 - 行btn 重试 （即，导入重试）
const tautology = e => {
  if (e.target.querySelector('input')) {
    e.target.querySelector('input').click();
  }
};
// 任务列表 - 导入任务 - table 数据 - 行btn 【下载】 -- 仅限 2-部分失败 和 3-失败 的展示下载，1-成功 的不展示下载
const downloadExcel = (data, val) => {
  // retry 场景已经没有 - 迁移前的上一版 入口按钮 已经干掉了 -- 迁移注释
  if (val == 'retry') {
    if (data.FileURL) {
      // flagok 2024.4.13 修复 重试 bug
      importData(data.FileURL, data.FileName);
    }
  } else {
    if (data.FileURL) {
      fileToBase64(
        window.TeldWebConfig.ResourceURL + '/' + data.FileURL,
        data.FileName,
      );
    }
  }
};
// 任务列表 - 导入任务 - table 数据 - 行btn 删除
const deleteLine = data => {
  const title = i18nTranslate(Terms.notify.deletionTask.ReferenceExpr, '删除任务') // TermsTranslated.notify.deletionTask || '删除任务';
  const message = (TermsTranslated.notify.deleteThisData || '删除本条数据') + '?'
  const cancel = true;
  const funOk = () => {
    TFF.common.ajax
      .getDataAsync({
        url: Funcs.FasRequestTagAdd(
          TFF.common.ajax.getServiceUrl('FASR-DeleteImportTask'),
        ),
        type: 'post',
        data: {
          taskID: data.ID,
        },
      })
      .then(data => {
        if (data.state) {
          if (data.state == 1) {
            totalCount.value--;
            GoPage(pageIndex.value);
          } else {
            // $q.notify({
            //   closeBtn: true,
            //   type: 'warning',
            //   position: 'bottom-right',
            //   message: `${data.errmsg}`,
            // });
            // i18n
            Funcs.Notify(TermsTranslated.title.notify, data.errmsg, 'warning');
          }
        }
      });
  };
  Funcs.Confirm(
    title,
    message,
    () => funOk(),
    () => {},
    '',
    { cancel, type: 'warning' },
  );
  // $q.dialog({
  //   title,
  //   message,
  //   cancel: true,
  // }).onOk(() => {
  //   funOk()
  // })
};
// 任务列表 - 导入任务 - table 数据 - 行btn 失败行数(有值时) - 查看失败详情列表
const viewDetai = data => {
  // let index = data.rowIndex;
  // let taskID = this.ImportTasklist[index].ID;
  let taskID = data.ID;
  getFailTaskDetail(taskID);
};
//获取失败任务列表
const getFailTaskDetail = taskID => {
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-GetImportTaskDetailList'),
      ),
      type: 'post',
      data: {
        taskID: taskID,
        filter: JSON.stringify({
          pageSize: 50,
          pageIndex: pageIndex.value,
        }),
      },
    })
    .then(data => {
      if (data.state == 1) {
        failTasklist.value = data.data;
      } else {
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `${data.errmsg}`,
        // });
        Funcs.Notify(TermsTranslated.title.notify, data.errmsg, 'warning');
      }
      showFailTasklistPopup.value = !showFailTasklistPopup.value;
    });
};
// == 原来的出码用到的 Props - end ==
// 继续新加方法

// 确认导入
const confirmSheet = () => {
  dialogSheet.value = false;
  if (importFlag.value == 'again') {
    // 重试
    uploadFileAgain();
  } else {
    importData();
  }
};
//导入确认 flagok -- 用到的机会不多
const uploadFileAgain = (url, fileName) => {
  if (!checkCdo()) {
    return;
  }

  const dialogIng = { hide: () => {} }
  // 不需要了，接口性能太好，弹出提示反而会闪烁 导致体验不佳 => 或者 Funcs.Confirm 支持返回变量 关闭,  用 Funcs.Confirm 也行 => 上面一行代码仅占位
  // const title = '提示';
  // const message = '正在导入...';
  // const ok = '我知道了';
  // const cancel = '';
  // // flagok 此处先不替换，因为 Funcs.Confirm 没支持 用代码 关闭
  // const dialogIng = $q
  //   .dialog({
  //     title,
  //     message,
  //     ok,
  //     cancel,
  //   })
  //   .onOk(() => {

  //   });
  let importDefs = [];
  if (importConfigComputed.value.defineDataSocurce) {
    let defineDataSocurce = JSON.parse(
      JSON.stringify(importConfigComputed.value.defineDataSocurce),
    );
    importDefs = defineDataSocurce.filter(item => {
      item.ImportRule = item.ImportRules;
      if (item.Parameters) {
        // flag-Promise.all
        item.Parameters.map(async j => {
          if (j.ParameterValue) {
            // j.ParameterValue = executeScript(j.ParameterValue).result;
            if (/^return/.test(j.ParameterValue.trim())) {
              j.ParameterValue = executeScript(j.ParameterValue);
            } else {
             j.ParameterValue = await executeScript('return ' + j.ParameterValue);
            }
          }
          return j;
        });
      }

      return item.isShow || item.ImportRules == 2;
    });
  }
  let dataQueryID = '';
  if (importConfigComputed.value.CdoSource.Value.Children) {
    importConfigComputed.value.CdoSource.Value.Children.map(item => {
      if (item.TreeItemID == 'DQ') {
        dataQueryID = item.ID;
      }
    });
  }

  TFF.common.ajax
  .getDataAsync({
    url: Funcs.FasRequestTagAdd(TFF.common.ajax.getServiceUrl('FASR-Retry')),
    type: 'post',
    data: {
      // taskID: retryJson.value.data.ID,
      taskID: retryJson.value.ID,
      importParam: JSON.stringify({
        CDOID: importConfigComputed.value.CdoSource.Value.ID,
        Script: importConfigComputed.value.defineData,
        MaxRow: importConfigComputed.value.MaxRows, //最大行数
        ImportStrategy: importConfigComputed.value.ImportStrategy, //导入策略，0更新记录、1忽略并记录
        FileURL: uploadUrl.value, //资源服务地址
        DataQueryID: dataQueryID, //DQID
        FileName: uploadName.value, //本地路径
        SheetName: SheetName.value, //Sheet页名称
        isEnableUniqueCol: importConfigComputed.value?.hasOwnProperty(
          'IsEnableUniqueCol',
        )
          ? importConfigComputed.value.IsEnableUniqueCol
          : true,
        isEnableExplainRow: importConfigComputed.value?.hasOwnProperty(
          'IsEnableExplainRow',
        )
          ? importConfigComputed.value?.IsEnableExplainRow
          : true,
      }),
      importDefs: JSON.stringify(importDefs),
      importVariables: importConfigComputed.value.VarDataSource
        ? JSON.stringify(importConfigComputed.value.VarDataSource)
        : JSON.stringify([]), //全局变量
    },
  })
    .then(data => {
      if (data.state == 1) {
        // 原来无逻辑 - 加入刷新逻辑
        getTaskList('Refresh')
      } else {
          // $q.notify({
          //   closeBtn: true,
          //   type: 'warning',
          //   position: 'bottom-right',
          //   message: `导入失败,失败原因：${data.errmsg}`,
          // });
          Funcs.Notify(
            TermsTranslated.title.notify,
            `${TermsTranslated.notify.importFail}：${data.errmsg}`,
            'warning',
          );
        // self.$message({
        //   message: `${Terms.notify.importFail}：${data.errmsg}`,
        //   type: "warning",
        //   showClose: true,
        // });
      }
      setTimeout(() => {
        emit('afterImport', { taskID: data.data ? data.data.ID : '' });
      }, 500);
      setTimeout(() => {
        dialogIng.hide();
      }, 500);
  })
    .catch(() => {
      dialogIng.hide();
    });
};
// 辅助变量
const uploadUrl = ref('');
const uploadName = ref('');
const importFlag = ref('');
// 辅助函数
const getBase64 = file => {
  return new Promise((resolve, reject) => {
    ///FileReader类就是专门用来读文件的
    const reader = new FileReader();
    //开始读文件
    //readAsDataURL: dataurl它的本质就是图片的二进制数据， 进行base64加密后形成的一个字符串，
    reader.readAsDataURL(file);
    // 成功和失败返回对应的信息，reader.result一个base64，可以直接使用
    reader.onload = () => resolve(reader.result);
    // 失败返回失败的信息
    reader.onerror = error => reject(error);
  });
};
// 读取cookie
const getCookie = c_name => {
  if (document.cookie.length > 0) {
    var c_start = document.cookie.indexOf(c_name + '=');
    if (c_start != -1) {
      c_start = c_start + c_name.length + 1;
      var c_end = document.cookie.indexOf(';', c_start);
      if (c_end == -1) c_end = document.cookie.length;
      return unescape(document.cookie.substring(c_start, c_end));
    }
  }
  return '';
};
// 导入 - 选中-确认-读取文件后 - 上传文件成功后
const importConfirmation = (url, name, val) => {
  uploadUrl.value = url;
  uploadName.value = name;
  let importDefs = [];
  if (importConfigComputed.value.defineDataSocurce) {
    let defineDataSocurce = JSON.parse(
      JSON.stringify(importConfigComputed.value.defineDataSocurce),
    );
    importDefs = defineDataSocurce.filter(item => {
      item.ImportRule = item.ImportRules;
      if (item.Parameters) {
        // flag-Promise.all
        item.Parameters.map(async j => {
          if (j.ParameterValue) {
            // j.ParameterValue = executeScript(j.ParameterValue).result;
            if (/^return/.test(j.ParameterValue.trim())) {
              j.ParameterValue = executeScript(j.ParameterValue);
            } else {
              j.ParameterValue = await executeScript('return ' + j.ParameterValue);
            }
          }
          return j;
        });
      }
      return item.isShow || item.ImportRules == 2;
    });
  }
  TFF.common.ajax
    .getDataAsync({
      // 会检测 excel 有几个 sheet
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-ImportConfirm'),
      ),
      type: 'post',
      data: {
        fileURL: url,
        importDefs: JSON.stringify(importDefs),
        isEnableUniqueCol: importConfigComputed.value?.hasOwnProperty(
          'IsEnableUniqueCol',
        )
          ? importConfigComputed.value.IsEnableUniqueCol
          : true,
        isEnableExplainRow: importConfigComputed.value?.hasOwnProperty(
          'IsEnableExplainRow',
        )
          ? importConfigComputed.value.IsEnableExplainRow
          : true,
      },
    })
    .then(data => {
      // 一个 response 的 demo
      // {
      //   "state": "1",
      //   "sheets": [
      //       {
      //           "SheetName": "Sheet0",
      //           "RowNum": 2
      //       },
      //       {
      //           "SheetName": "Sheet1",
      //           "RowNum": 1
      //       }
      //   ]
      // }
      // 等待改造 - OK
      if (data.state == 1) {
        // dialogVisibleTip 为旧版本字段
        dialogSheet.value = false;
        nextTick(() => {
          sheetList.value = data.sheets;
          SheetName.value = data.sheets[0].SheetName;
          // 洗一下数据，不然 t-select 数据传参需要变
          sheetList.value.forEach(item => {
            item.label = item.SheetName;
            item.value = item.SheetName;
          });
          // RowNum = data.sheets[0].RowNum; // 迁移, 代码优化：删除本行，原因为， 1.RowNum 是 computed 属性，不可修改，2.computed 里面已经的逻辑与此处相同
          importFlag.value = val;
          if (sheetList.value.length != 1) {
            dialogSheet.value = true;
            // const title = `是否要执行 ${RowNum.value} 条数据的导入?`
            // const message = `<div style="color: red;">自定义</div>`
            // const cancel = true
            // const funOk = () => confirmSheet()
            // Funcs.Confirm(title, message, () => funOk(), () => {}, true, {cancel})
          } else {
            // 之前的逻辑 -- 直接调用上传, 没有判断是否 是 '重试'
            // importData(url, name);
            // 2024.4.13 迁移 修复之前 bug
            // 这里应该加入判断, 如果是 '重试'上传, 则调用 uploadFileAgain, 否则调用 importData

            if (importFlag.value == 'again') {
              // 重试
              uploadFileAgain();
            } else {
              importData(url, name);
            }
          }
        });
      } else {
        Funcs.Notify(
          TermsTranslated.title.notify,
          `${TermsTranslated.notify.failReason}：${data.errmsg}`,
          'warning',
        );
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `失败原因：${data.errmsg}`,
        // });
      }
    });
};
const importData = (url, fileName) => {
  // 1.用 emit 出去 的 beforeImport
  emit('beforeImport', arguments);
  // 或 接收的 props的 beforeImport  都行
  // beforeImport();
  2;
  // 如下，废弃老方法
  // let self = this;

  // instanceCode 需要传给我
  let instanceCode = mappingProps.instanceCode;
  // let JSScript = findEventByName('beforeImport').JSScript;
  // 上一行改为
  let JSScript = mappingProps.beforeImportJSScript;
  // 迁移时，简述下方代码作用，业务脚本 JSScript 中存在 import2 -- 导入函数 -- 则我们不执行就不执行 import2, 否则避免重复执行 import2
  let hasFunction = true;
  let isNot = false;
  if (JSScript.indexOf('.' + instanceCode + '.import2') != -1) {
    let JSScriptArr = JSScript.split('\n');
    JSScriptArr.forEach(item => {
      if (item.indexOf('.' + instanceCode + '.import2') != -1) {
        let Params = item.split(';');
        let index = Params.findIndex(
          item => item.indexOf('.' + instanceCode + '.import2') != -1,
        );
        if (
          Params[index] &&
          !(
            Params[index].indexOf('*') == -1 &&
            Params[index].indexOf('//') == -1
          )
        ) {
          hasFunction = false;
        } else {
          isNot = true;
        }
      }
    });
  } else {
    hasFunction = false;
  }

  if (hasFunction || isNot) {
  } else {
    import2(url, fileName);
  }
};
// 迁移, 原来的 import 函数
const import2 = async (url, fileName) => {
  // let self = this;
  if (!checkCdo()) {
    return;
  }

  const dialogIng = { hide: () => {} }

  // http://resource.teld.cc/telddoc/107/97b9c9930cd043cfba7e5efcd0aa4964.xlsx
  let importDefs = [];
  if (importConfigComputed.value.defineDataSocurce) {
    let defineDataSocurce = JSON.parse(
      JSON.stringify(importConfigComputed.value.defineDataSocurce),
    );
    importDefs = defineDataSocurce.filter(item => {
      item.ImportRule = item.ImportRules;
      if (item.Parameters) {
        // flag-Promise.all
        item.Parameters.map(async j => {
          if (j.ParameterValue) {
            // j.ParameterValue = executeScript(j.ParameterValue).result;
            if (/^return/.test(j.ParameterValue.trim())) {
              j.ParameterValue = executeScript(j.ParameterValue);
            } else {
              j.ParameterValue = await executeScript('return ' + j.ParameterValue);
            }
          }
          return j;
        });
      }
      return item.isShow || item.ImportRules == 2;
    });
  }
  let dataQueryID = '';
  if (importConfigComputed.value.CdoSource.Value.Children) {
    importConfigComputed.value.CdoSource.Value.Children.map(item => {
      if (item.TreeItemID == 'DQ') {
        dataQueryID = item.ID;
      }
    });
  }
  if (importConfigComputed.value.VarDataSource) {
    importConfigComputed.value.VarDataSource = await Promise.all(
      importConfigComputed.value.VarDataSource.map(async item => {
        if (item.ParamType == 1) {
          // item.ParamValue = executeScript(item.Script).result; // executeScript(xxx).result 是旧的写法
          // 用这种 await 的形式 2024.4.18 flagok
          if (/^return/.test(item.Script.trim())) {
            item.ParamValue = executeScript(item.Script);
          } else {
            item.ParamValue = await executeScript('return ' + item.Script);
          }
        }
        return item;
      })
    )
  }
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-ImportDataNew'),
      ),
      type: 'post',
      data: {
        importParam: JSON.stringify({
          CDOID: importConfigComputed.value.CdoSource.Value.ID,
          Script: importConfigComputed.value.defineData,
          MaxRow: importConfigComputed.value.MaxRows, //最大行数
          FileURL: uploadUrl.value, //资源服务地址
          DataQueryID: dataQueryID, //DQID
          FileName: uploadName.value, //本地路径
          ImportStrategy: importConfigComputed.value.ImportStrategy, //导入策略，0更新记录、1忽略并记录
          IsEnableUniqueCol: importConfigComputed.value?.hasOwnProperty(
            'IsEnableUniqueCol',
          )
            ? importConfigComputed.value.IsEnableUniqueCol
            : true,
          IsEnableExplainRow: importConfigComputed.value?.hasOwnProperty(
            'IsEnableExplainRow',
          )
            ? importConfigComputed.value.IsEnableExplainRow
            : true,
          SheetName: SheetName.value, //Sheet页名称
        }),
        importDefs: JSON.stringify(importDefs),
        importVariables: importConfigComputed.value.VarDataSource
          ? JSON.stringify(importConfigComputed.value.VarDataSource)
          : JSON.stringify([]), //全局变量
      },
    })
    .then(data => {
      if (data.state == 1) {
        importInterval.value=0
        // $q.notify({
        //   closeBtn: true,
        //   type: 'success',
        //   position: 'bottom-right',
        //   message: `已创建导入任务`,
        // });
        Funcs.Notify(
          TermsTranslated.title.notify,
          TermsTranslated.notify.importSuccess,
          'success',
        );
        // self.$message({
        //   message: Terms.notify.importSuccess,
        //   type: "success",
        //   showClose: true,
        // });
      } else {
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `失败原因：${data.errmsg}`,
        // });
        Funcs.Notify(
          TermsTranslated.title.notify,
          `${TermsTranslated.notify.failReason}：${data.errmsg}`,
          'warning',
        );
      }
      setTimeout(() => {
        emit('afterImport', { taskID: data.data ? data.data.ID : '' });
        // try {
        //   self.triggerEventHandler('AfterImport', {
        //     taskID: data.data ? data.data.ID : '',
        //   });
        // } catch (err) {
        //   Funcs.Notify(Terms.title.notify, err.message, 'warning');
        //   // self.$message({
        //   //   message: err.message,
        //   //   type: "warning",
        //   // });
        // }
      }, 500);
      setTimeout(() => {
        dialogIng.hide();
      }, 500);
      // 迁移 - 原来的清除弹窗
      // setTimeout(() => {
      // self.$msgbox.close();
      // }, 500);
    })
    .catch(() => {
      dialogIng.hide();
    })
    .finally(() => {
      setTimeout(() => {
        dialogIng.hide();
      }, 500);
    });
};
// 展示任务列表导入导出数据
const GetImportTaskList = () => {
  dialog.value = true;
  nextTick(() => {
    tabsComp.value.currentTabIndex = tab.value;
  });
  // 默认就是这个
  // pageSize.value = 10;
  // pageIndex.value = 1;
  getTaskList();
};
const hasLoadingTask = (rows)=>{
  if(!rows) return false
  return rows.find(item=>item.State == 0)
}
// 获取任务列表导入导出数据
const getTaskList = async isRefresh => {
  if (tab.value * 1 === 0) {
    // q-tabs 用
    // 获取导入任务列表
    await refreshGetImportTaskList();
    if(hasLoadingTask(rowsIm.value)){

    }
  } else if (tab.value === 1) {
    // q-tabs 用
    // 获取导出任务列表
    await refreshGetExportTaskList();
  }
  if (isRefresh) {
    Funcs.Notify(TermsTranslated.title.notify, TermsTranslated.title.refreshSuccess, 'success');
    // $q.notify({
    //   closeBtn: true,
    //   type: 'success',
    //   position: 'bottom-right',
    //   message: `数据刷新成功`,
    // });
  }
};
// 获取导入任务列表
// const refreshGetImportTaskList = () => {}
const importTimer = ref(null)
const exportTimer = ref(null)
const delayTimeList = [5.1,5.2,5.3,15,30,60]
const importInterval = ref(0)
const exportInterval = ref(0)
onUnmounted(()=>{
  if(importTimer.value){
    window.clearTimeout(importTimer.value)
    importTimer.value=null
  }
  if(exportTimer.value){
    window.clearTimeout(exportTimer.value)
    exportTimer.value=null
  }
})
watch(()=> dialog.value,()=>{
  if(! dialog.value){
    if(importTimer.value){
    window.clearTimeout(importTimer.value)
    importTimer.value=null
  }
  if(exportTimer.value){
    window.clearTimeout(exportTimer.value)
    exportTimer.value=null
  }
  }else{
    importInterval.value=0
   exportInterval.value=0
  }
})
const refreshGetImportTaskList = () => {
  if (!checkCdo()) {
    return;
  }
  if(importTimer.value){
    window.clearTimeout(importTimer.value)
    importTimer.value=null
  }
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-GetImportTaskList'),
      ),
      type: 'post',
      data: {
        cdoID: importConfigComputed.value.CdoSource.Value.ID,
        filter: JSON.stringify({
          pageSize: pageSize.value,
          pageIndex: pageIndex.value,
        }),
      },
    })
    .then(data => {
      if (data.state == 1) {
        rowsIm.value = data.data;
        rowsIm.value = rowsIm.value.slice(0);
        totalCount.value = data.total;
        if(hasLoadingTask(rowsIm.value)){
          if(importInterval.value===0){
            importInterval.value=delayTimeList[0]
          }else{
            let index = delayTimeList.indexOf(importInterval.value)
            importInterval.value = delayTimeList[index*1+1]
            if(!importInterval.value ){
              importInterval.value =delayTimeList[delayTimeList.length-1]
            }
          }
          importTimer.value = window.setTimeout(()=>{
            refreshGetImportTaskList()
          },parseInt(importInterval.value)*1000)
        }
      } else {
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `失败原因：${data.errmsg}`,
        // });
        Funcs.Notify(
          TermsTranslated.title.notify,
          `${TermsTranslated.notify.failReason}：${data.errmsg}`,
          'warning',
        );
      }
    });
  // 迁移前，老的写法
  // window.getDataAsync(
  //   fasRequestTagAdd(window.FrameSGHost + 'FASR-GetImportTaskList'),
  //   'POST',
  //   {
  //     cdoID: importConfigComputed.value.CdoSource.Value.ID,
  //     filter: JSON.stringify({
  //       pageSize: pageSize.value,
  //       pageIndex: pageIndex.value,
  //     }),
  //   },
  //   function (data) {
  //     if (data.state == 1) {
  //       rowsIm = data.data;
  //       rowsIm = rowsIm.slice(0);
  //       totalCount.value = data.total;
  //     } else {
  //       $q.notify({
  //         closeBtn: true,
  //         type: 'warning',
  //         position: 'bottom-right',
  //         message: `失败原因：${data.errmsg}`,
  //       });
  //     }
  //   },
  //   function () {
  //   },
  // );
};
// 来自 BaseFasCcomponent
// const findEventByName = (events, eventName) => {
//   ... 10行
// };
// 来自 BaseFasCcomponent
// triggerEventHandler + triggerEvent 废弃，老版本未了 emit 事件的
// const triggerEventHandler = (eventName, args, immediate) => {
//   ... 近30行
//   triggerEvent
// };
// const triggerEvent = (eventName, args) => {
// ... 40行
// };

const checkCdo = () => {
  // 语法优化
  // if (!importConfigComputed.value.CdoSource.Value && !importConfigComputed.value.CdoSource.Value.ID) {
  if (!importConfigComputed.value?.CdoSource?.Value?.ID) {
    Funcs.Notify(TermsTranslated.title.notify, TermsTranslated.title.checkCdo, 'warning');
    // $q.notify({
    //   closeBtn: true,
    //   type: 'warning',
    //   position: 'bottom-right',
    //   message: '导入控件配置不完整，请选择CDO',
    // });
    return false;
  }
  return true;
  // 导入导出控件配置不完整，请选择cdo、DQ
};
// == 辅助函数 们 end ==

// 获取导出任务列表
const refreshGetExportTaskList = () => {
  if(exportTimer.value){
    window.clearTimeout(exportTimer.value)
    exportTimer.value=null
  }
  TFF.common.ajax
    .getDataAsync({
      url: Funcs.FasRequestTagAdd(
        TFF.common.ajax.getServiceUrl('FASR-GetExportTaskList'),
      ),
      type: 'post',
      data: {
        dataQueryID: exportConfigComputed.value.DataSource.ActionID,
        filter: JSON.stringify({
          pageSize: pageSize.value,
          pageIndex: pageIndex.value,
        }),
      },
    })
    .then(data => {
      if (data.state == 1) {
        rowsEx.value = data.data;
        rowsEx.value = rowsEx.value.slice(0);
        totalCount.value = data.total;
        if(hasLoadingTask(rowsEx.value)){
          if(exportInterval.value===0){
            exportInterval.value=delayTimeList[0]
          }else{
            let index = delayTimeList.indexOf(exportInterval.value)
            exportInterval.value = delayTimeList[index*1+1]
            if(!exportInterval.value ){
              exportInterval.value =delayTimeList[delayTimeList.length-1]
            }
          }
          exportTimer.value = window.setTimeout(()=>{
            refreshGetExportTaskList()
          },parseInt(exportInterval.value)*1000)
        }
      } else {
        // $q.notify({
        //   closeBtn: true,
        //   type: 'warning',
        //   position: 'bottom-right',
        //   message: `失败原因：${data.errmsg}`,
        // });
        Funcs.Notify(
          TermsTranslated.title.notify,
          `${TermsTranslated.notify.failReason}：${data.errmsg}`,
          'warning',
        );
        // self.$message({
        //   message: `${Terms.notify.failReason}：${data.errmsg}`,
        //   type: "warning",
        //   showClose: true,
        // });
      }
    })
    .catch(e => {});
};
// 预览 -
const previewFile = data => {
  // Funcs.PreviewFile 不变
  // 迁移, window.ResourcePath => window.TeldWebConfig.ResourceURL
  if (!previewFileEnable.value) return;
  Funcs.PreviewFile(
    data.FileName,
    window.TeldWebConfig.ResourceURL + '/' + data.FileURL,
  );
};
// 设置是否可下载css （样式)
const getDownLoadCss = (data, showColor) => {
  if (!showColor) return '';
  if (data.FileURL) {
    return 'canDownload';
  }
  return 'DISPLAY_NONE';
};
// 下载导出文件
const downExportloadExcel = data => {
  // 迁移, window.ResourcePath => window.TeldWebConfig.ResourceURL
  if (data.FileURL) {
    fileToBase64(
      window.TeldWebConfig.ResourceURL + '/' + data.FileURL,
      data.FileName,
    );
  }
};
// 下载导出文件 - 辅助函数 == start
const fileToBase64 = (fileUrl, name) => {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', fileUrl, true);
  xhr.responseType = 'blob';
  xhr.onload = function () {
    // 迁移, 这个 this 是此处局部域的
    if (this.status === 200) {
      var blob = this.response;
      if (window.FileReader) {
        var reader = new FileReader();
        reader.onloadend = function () {
          var base64Data = reader.result;
          downloadFileByBase64(base64Data, name);
        };
        reader.readAsDataURL(blob);
      } else {
        var myUrl = URL.createObjectURL(blob);
        downloadFile(myUrl, name);
      }
    }
  };
  xhr.send();
};

const downloadFileByBase64 = (base64, name) => {
  var myBlob = dataURLtoBlob(base64);
  var myUrl = URL.createObjectURL(myBlob);
  downloadFile(myUrl, name);
};
const dataURLtoBlob = dataurl => {
  var arr = dataurl.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
};

const downloadFile = (url, name) => {
  var a = document.createElement('a');
  a.setAttribute('href', url);
  a.setAttribute('download', name);
  a.setAttribute('target', '_blank');
  let clickEvent = document.createEvent('MouseEvents');
  clickEvent.initEvent('click', true, true);
  a.dispatchEvent(clickEvent);
};
// 下载导出文件 - 辅助函数 == end

// 删除 - 删除一条导出任务
const deleteExportLine = data => {
  const title = i18nTranslate(Terms.notify.deletionTask.ReferenceExpr, '删除任务') // TermsTranslated.notify.deletionTask || '删除任务';
  const message = (TermsTranslated.notify.deleteThisData || '删除本条数据') + '?'
  const cancel = true;
  const funOk = () => {
    TFF.common.ajax
      .getDataAsync({
        url: Funcs.FasRequestTagAdd(
          TFF.common.ajax.getServiceUrl('FASR-DeleteExportTask'),
        ),
        type: 'post',
        data: {
          taskID: data.ID,
        },
      })
      .then(data => {
        if (data.state == 1) {
          totalCount.value--;
          GoPage(pageIndex.value);
        } else {
          // $q.notify({
          //   closeBtn: true,
          //   type: 'warning',
          //   position: 'bottom-right',
          //   message: `${data.errmsg}`,
          // });
          Funcs.Notify(
            TermsTranslated.title.notify,
            `${data.errmsg}`,
            'warning',
          );
        }
      });
  };
  Funcs.Confirm(
    title,
    message,
    () => funOk(),
    () => {},
    '',
    { cancel, type: 'warning' },
  );
  // $q.dialog({
  //   title: '',
  //   message: '删除本条数据?',
  //   cancel: true,
  // }).onOk(() => {
  //   funOk()
  // });
};
const GoPage = page => {
  if (page >= 1 && totalCount.value > 0) {
    if (page <= Math.ceil(totalCount.value / pageSize.value)) {
      pageIndex.value = page;
    } else {
      pageIndex.value = Math.ceil(totalCount.value / pageSize.value);
    }
  } else {
    pageIndex.value = 1;
  }
  getTaskList();
};
// 清空导入任务
const clearnImportList = () => {
  const title = i18nTranslate(Terms.notify.clearTask.ReferenceExpr, '清空任务列表') // TermsTranslated.notify.clearTask || '清空任务列表';
  const message = (TermsTranslated.notify.clearImportTask || '清空导入任务列表') + '?'
  const cancel = true;
  const funOk = () => {
    TFF.common.ajax
      .getDataAsync({
        url: Funcs.FasRequestTagAdd(
          TFF.common.ajax.getServiceUrl('FASR-ClearImportTask'),
        ),
        type: 'post',
        data: {
          cdoID: importConfigComputed.value.CdoSource.Value.ID,
        },
      })
      .then(data => {
        if (data.state == 1) {
          pageIndex.value = 1;
          totalCount.value = 0;
          totalPage.value = 0;
          failTasklist.value = [];
          rowsIm.value = [];
        }
      });
  };
  Funcs.Confirm(
    title,
    message,
    () => funOk(),
    () => {},
    '',
    { cancel, type: 'warning' },
  );
  // $q.dialog({
  //   title: '',
  //   message: '清空导入任务列表?',
  //   cancel: true,
  // }).onOk(() => {
  //   funOk()
  // });
};
// 清空导出任务
const clearnExportList = () => {
  const title = i18nTranslate(Terms.notify.clearTask.ReferenceExpr, '清空任务列表') // TermsTranslated.notify.clearTask || '清空任务列表';
  const message = (TermsTranslated.notify.clearExportTask || '清空导出任务列表') + '?'
  const cancel = true;
  const funOk = () => {
    TFF.common.ajax
      .getDataAsync({
        url: Funcs.FasRequestTagAdd(
          TFF.common.ajax.getServiceUrl('FASR-ClearExportTask'),
        ),
        type: 'post',
        data: {
          metaDataID: exportConfigComputed.value.DataSource.ActionID,
        },
      })
      .then(data => {
        if (data.state == 1) {
          pageIndex.value = 1;
          totalCount.value = 0;
          totalPage.value = 0;
          // 迁移, 优化, 清空 导出任务别表 时 - 导入异常列表没必要清空 (仅清空 导入任务列表 时, 清空 导入异常列表 即可)
          // failTasklist.value = []
          rowsEx.value = [];
        }
      });
  };
  Funcs.Confirm(
    title,
    message,
    () => funOk(),
    () => {},
    '',
    { cancel, type: 'warning' },
  );
  // $q.dialog({
  //   title: '',
  //   message: '清空导出任务列表?',
  //   cancel: true,
  // }).onOk(() => {
  //   funOk()
  // });
};
//
//
//
// data

const tipsWord = ref(i18nTranslate(Terms.title.importDes.ReferenceExpr, '系统将默认保留文件3个月，请及时处理'));
const inDesign = ref(!!window['fas']?.inDesign);
const upload = ref(null);
// 任务列表 - 导出任务 - table 表头 -- ⬆️
const columnsEx = reactive([
  {
    name: 'State',
    label: i18nTranslate(Terms.title.State.ReferenceExpr, '状态'),
    field: 'State',
    align: 'center',
    sortable: false,
  },
  {
    name: 'Name',
    label: i18nTranslate(Terms.title.exportTaskName.ReferenceExpr, '导出任务名称'),
    field: 'Name',
    align: 'left',
    sortable: false,
  },
  {
    name: 'FileName',
    label: i18nTranslate(Terms.title.FileName.ReferenceExpr, '文件名'),
    field: 'FileName',
    align: 'left',
    sortable: false,
  },
  {
    name: 'FileSize',
    label: i18nTranslate(Terms.title.FileSize.ReferenceExpr, '文件大小'),
    field: 'FileSize',
    align: 'left',
    sortable: false,
  },
  { name: 'RowNum', label: i18nTranslate(Terms.title.RowNums.ReferenceExpr, '导出行数'), field: 'RowNum', sortable: false },
  {
    name: 'ElapsedSeconds',
    label: i18nTranslate(Terms.title.ElapsedSeconds.ReferenceExpr, '耗时(秒)'),
    field: 'ElapsedSeconds',
    sortable: false,
  },
  {
    name: 'ExportTime',
    label: i18nTranslate(Terms.title.ExportTime.ReferenceExpr, '导出时间'),
    field: 'ExportTime',
    align: 'left',
    sortable: false,
  },
  {
    name: 'ErrMsg',
    label: i18nTranslate(Terms.title.ExportErrMsg.ReferenceExpr, '失败原因'),
    field: 'ErrMsg',
    align: 'left',
    sortable: false,
  },
  {
    name: 'Operation',
    label: i18nTranslate(Terms.title.operation.ReferenceExpr, '操作'),
    field: 'Operation',
    align: 'center',
    sortable: false,
  },
]);
// 任务列表 - 导出任务 - 迁移, 原 ExportTasklist 字段
const rowsEx = ref([
  // {
  //   ID: '4cf738d0-5c9a-476b-befc-6962144b56b0',
  //   Name: '20240314174416396',
  //   State: 0,
  //   RowNum: 0,
  //   ErrMsg: '',
  //   FileName: '',
  //   FileURL: '',
  //   FileSize: '',
  //   ElapsedSeconds: 0.0,
  //   ExportTime: '刚刚',
  // },
  // {
  //   ID: 'e2dd0bb0-6c3f-4885-ab33-c35255e0816a',
  //   Name: '20240314163355139',
  //   State: 1,
  //   RowNum: 20,
  //   ErrMsg: '',
  //   FileName: '20240314163355139.xlsx',
  //   FileURL: 'telddoc/141/FASExport-20240314163355139.xlsx',
  //   FileSize: '5KB',
  //   ElapsedSeconds: 0.35,
  //   ExportTime: '1小时前',
  // },
  // {
  //   State: 2,
  // },
  // {
  //   State: 3,
  // },
]);
// computed
const RowNum = computed(() => {
  if (sheetList.value) {
    let target = sheetList.value.find(
      item => item.SheetName == SheetName.value,
    );
    if (!target) return 0;
    return target.RowNum;
  }
  return 0;
});
const importConfigComputed = computed(() => {
  return typeof mappingProps.importConfig === 'string'
    ? JSON.parse(mappingProps.importConfig)
    : mappingProps.importConfig;
});
const exportConfigComputed = computed(() => {
  const exportConfig = typeof mappingProps.exportConfig === 'string'
    ? JSON.parse(mappingProps.exportConfig)
    : mappingProps.exportConfig;
  // 参考
  //条件名称转换 国际化
  // fieldName:
  //   Funcs.GetTerms(
  //     item?.ValueInfo_fieldName?.ReferenceExpr,
  //     item.fieldName,
  //   ) || item.fieldName,
  // 导出的字段名 - 国际化 -- 因为国际化的所需的词条信息已经放到我们这个信息数组里了
  exportConfig?.Columns?.forEach(item => {
    item.ExcelColName = Funcs.GetTerms(item?.ValueInfo_ExcelColName?.ReferenceExpr, item.ExcelColName) || item.ExcelColName
  })
  return exportConfig
});
const [mappingProps, mappingExpose] = useMappingProps(props, {
  upload,
  $q,
  import2,
});
defineExpose({ ...mappingExpose, export2, import2, handleImport, handleExport2, dowmloadTemplate, handleMissionList });
// methods
// getFile - 迁移后改方法名称 -> getImportFile
const getFile = async (e, val, data) => {
  getImportFile(e, val, data);
};
// table
const handleClickState = props => {
  console.log('props.rows', props.row, '--- props ---', props);
};
const onRequest = (props) => {
  updatePagination(props.pagination)
}
const updatePagination = newPagination => {
  // 迁移, 此处方法触发 太容易了，容易重复调接口 flag
  const { rowsPerPage, page } = newPagination;
  pageSize.value = rowsPerPage;
  pageIndex.value = page;
  getTaskList();
};
// 点击事件
// const onClickHandler = params => {
//   emit('click', params);
// };
</script>

<style lang="scss">
/* dialog 的公共样式， 方便以后提取 */
.t-import-export-dialog {
  @import './dialog.scss';
}
// table 样式重置
.t-import-export-dialog {
  @import './table.scss';
}
</style>
<style lang="scss">
.t-import-export {
  position: relative;
}

.t-import-export-dialog.dialog-mission-list {
  // table 自定义 rows-per-page-options, 切换分页大小，防止本区域抖动(无意义滚动条产生)
  .standard-tabs .q-tab-panel {
    overflow: hidden;
  }
  .close-actions {
    margin-top: 0;
  }
}
.t-import-export-dialog,
.t-import-export {
  .primary-color {
    color: var(--q-primary);
  }
  .pointer {
    cursor: pointer;
  }
  .svg-icon {
    width: 14px;
    height: 14px;
    vertical-align: middle;
  }
  .t-checkbox .q-checkbox__bg {
    // border-color: rgba(0, 0, 0, .32); // 不需要，用统一的公共样式 -- 主色
  }
  .input-upload {
    opacity: 0;
    position: fixed;
    width: 0;
    height: 0;
  }

  .q-tabs__content {
    .absolute-bottom {
      z-index: 1;
    }
    &::after {
      z-index: 0;
      position: absolute;
      content: '';
      bottom: 0;
      left: 16px;
      right: 16px;
      border-bottom: 2px solid #e4e7ed;
    }
  }
  .sheet-card-section {
    display: flex;
    align-items: center;
    padding: 24px;
    .sheet-card-section-text {
      // flex-shrink: 0;
      flex: 0 1 auto;
      margin-right: 12px;
      font-size: 14px;
      color: rgb(51, 51, 51);

      max-width: 50%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .sheet-card-section > .sheet-card-section-select {
      flex: 0 1 auto;
      max-width: 50%;
  }
  .sheet-card-section-button-line {
    padding: 0 24px 16px;
  }
}
.t-import-export-list {
  user-select: none;
  .q-item,
  .t-item {
    white-space: nowrap;
    &:hover {
      cursor: pointer;
      background: #f0f2f5;
    }
  }
  .dropdown-button-text {
    vertical-align: middle;
  }
  // (都是14px，老图标偏大)，所以需要缩小一下
  .icon-shrink,
  .icon-shrink .q-icon {
    transform: scale(0.8);
  }
  // <Item>不支持 click 事件，<ItemSection> 支持 click 事件，所以把 padding 转移到 <ItemSection> 上
  .item-wrap {
    padding-left: 0;
    padding-right: 0;
  }
  .item-section {
    padding-left: 16px;
    padding-right: 16px;
  }
}

.t-import-export-dialog {
  // .my-sticky-column-table {
  // width: 1200px;
  // }
  /* 导出全部数据 */
  .ex-select-table {
    /* height or max-height is important */
    /* height: 310px; */
    max-height: calc(90vh - 48px - 74px - 32px - 33px);

    .q-table__top,
    .q-table__bottom,
    thead tr:first-child th {
      /* bg color is important for th; just specify one */
      background: #f5f5f5;
    }

    thead tr th {
      position: sticky;
      z-index: 1;
    }
    thead tr:first-child th {
      top: 0;
    }

    /* this is when the loading indicator appears */
    &.q-table--loading thead tr:last-child th {
      /* height of all previous header rows */
      top: 48px;
    }

    /* prevent scrolling behind sticky top row on focus */
    tbody {
      /* height of all previous header rows */
      scroll-margin-top: 48px;
    }
  }
  .ex-select-table-wrap {
    .q-table__middle.scroll {
      /* max-height: calc(100vh - 48px - 74px - 32px - 33px); // 这个是根据容器算出来的，恰巧不会有双滚动条 */
      max-height: calc(60vh - 48px - 74px - 32px - 33px);
      overflow-y: scroll;
    }
  }
  // 新版
  .export-all-section {
    .q-checkbox {
      width: 14px;
      height: 14px;
      margin-right: 12px; // 视觉8px
    }

    display: flex;
    justify-content: space-between;
    --el-bg-color-overlay: #ffffff;
    --el-transfer-panel-width: 200px;
    .transfer-panel {
      overflow: hidden;
      box-sizing: border-box;
      position: relative;
      display: inline-block;
      background: #fff;
      border: 1px solid #ebeef5;
      border-radius: 4px;
      width: 250px;
      max-height: 100%;
      vertical-align: middle;
      .transfer-panel__header {
        height: 40px;
        line-height: 40px;
        background: #f0f2f5;
        margin: 0;
        padding-left: 15px;
        padding-right: 15px;
        border-bottom: 1px solid #ebeef5;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        color: #000;
        .checkbox-wrap {
          position: relative;
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 100%;
          .checkbox-wrap-left {
            display: flex;
            .checkbox-word {
              flex-shrink: 0;
              line-height: 14px;
              font-size: 14px;
              color: rgba(0, 0, 0, var(--t-color-opacity, /*批量处理90%透明度*/0.9));
              vertical-align: middle;
            }
          }
          .checkbox-wrap-right {
            font-size: 12px;
            color: #909399;
          }
        }
      }
      .transfer-panel__filter {
        box-sizing: border-box;
        display: block;
        width: auto;
        margin: 8px 12px;
        text-align: center;
        .q-icon {
          transform: scale(1.1667); // 12px 是标准，太小了，放大为14px
        }
      }
      .transfer-panel__list {
        overflow: auto;
        box-sizing: border-box;
        list-style: none;
        margin: 0;
        padding: 6px 0;
        height: 254px;
        .transfer-panel__item {
          display: flex;
          align-items: center;
          cursor: pointer;
          user-select: none;
          padding-left: 12px;
          font-size: 14px;
          color: #606266;
          font-weight: 500;
          width: 100%;
          .checkbox__span {
            overflow: hidden;
            text-overflow: ellipsis;
            box-sizing: border-box;
            white-space: nowrap;
            display: block;
            line-height: 30px;
          }
        }
      }
    }
    .middle {
      display: flex;
      align-items: center;
      .middle-content {
        display: flex;
        flex-direction: column;
        justify-content: center;
        .transfer-button {
          box-sizing: border-box;
          min-width: 46px;
          width: 46px;
          height: 32px;
          margin: 4px 20px;
          .q-icon {
            font-size: 12px;
          }
        }
      }
    }
  }
  /* 导出全部数据 end */
  .func-line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: auto;
    margin-bottom: 8px;

    .tips {
      margin: 0;
      color: rgb(0, 0, 0, .56); // rgb(255, 149, 64); // 新UI规范 提示信息 .56 （迁移前版本的橙色 废弃)
      // font-weight: bold;
    }
    .custom-icon-refresh {
      height: 30px;
      line-height: 30px;
    }
  }
  /* tabs 相关样式 */
  .padding-top-0 {
    padding-top: 0;
  }
  .q-tabs {
    margin-bottom: 12px;
  }
  .q-tab-panels {
    padding-top: 0;
  }
  .q-tab-panels {
    padding: 16px; /* 原来是 padding: 16px; 现在没找到，但是确实应该有；所以加上 */
    padding-top: 0;
  }
  .my-sticky-column-table,
  .table-placeholder {
    height: 561px;
  }
  .my-sticky-column-table {
    td {
      color: rgba(0, 0, 0, var(--t-color-opacity, /*批量处理90%透明度*/0.9));
    }
  }
  .table-placeholder {
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .font-size-standard {
    font-size: 14px;
  }

  .operation-line {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .operation-line, .error-line, .file-name-line {
    .button-span {
      margin: 0 5px;
      padding: 0;
      min-width: auto;
    }
  }
  .error-line {
    .error-line-button {
      color: inherit;
      font-size: inherit;
      line-height: inherit;
      text-decoration: underline;
    }
  }
  .file-name-line {
    display: flex;
    align-items: center;
  }
  .canView {
    text-decoration: underline;
    color: var(--t-danger-color);
    cursor: pointer;
  }
  // 迁移, 迁移的两个class
  .canDownload {
    /* text-decoration: underline; */
    // color: blue;
    color: var(--q-primary);
    cursor: pointer;
  }

  .DISPLAY_NONE {
    display: none;
  }

  .dialog-wrap {
    // 6 = 24 - 4 - 14 // 标题文字 到 tab 文字的实际间距 - 标题行高下留白 - tab 上留白
    .q-card__section:nth-child(1) { // .dialog-title {
      margin-bottom: 6px;
    }
  }
  // table 自带分页组件 select 的focus效果 -- 参考自 select 组件
  .q-field--focused {
    border: 1px solid var(--t-color);
    box-shadow: 0 0 3px rgba(var(--t-color-rgb), 0.6);
  }
}
// 穿梭框 部分内容 适当留空间大一点
.t-import-export-dialog-mobile .export-all-section .transfer-panel .transfer-panel__header {
  padding-left: 10px;
  padding-right: 10px;
}

.t-import-export-list .t-item:focus {
  outline: none;
  background-color: rgb(240, 242, 245);
}
</style>
